Workbench运行SQL查询添加子查询后超时,此前正常该如何解决?
SQL查询超时问题排查与优化方案
问题根因
你当前的写法存在两个核心性能问题:
- 子查询未同步时间过滤条件:外层查询限制了
created_at < '2012-06-14',但内层子查询是对全表所有会话计算最小website_pageview_id,表数据量增长后,子查询会扫描全量历史数据,耗时陡增。 - MySQL对IN子查询的优化缺陷:老版本MySQL(5.6及之前)处理IN子查询时,会自动改写为相关子查询,外层每扫描一行数据就会重复执行一次内层子查询,时间复杂度直接升到O(n²),数据量大时必然超时。
优化方案
方案1:修正子查询过滤条件+替换为JOIN写法(最简便,无需临时表)
直接用内连接替代IN子查询,同时给内层查询加上相同的时间过滤条件,避免全表扫描:
SELECT p.website_session_id, p.website_pageview_id, p.pageview_url FROM website_pageviews p INNER JOIN ( SELECT website_session_id, MIN(website_pageview_id) AS first_pageview_id FROM website_pageviews WHERE created_at < '2012-06-14' -- 同步加时间过滤,仅计算符合条件的会话 GROUP BY website_session_id ) t ON p.website_pageview_id = t.first_pageview_id WHERE p.created_at < '2012-06-14';
方案2:添加联合索引进一步提速
给website_pageviews表添加联合索引,覆盖查询需要的所有字段,避免回表查询:
CREATE INDEX idx_created_session_page ON website_pageviews(created_at, website_session_id, website_pageview_id, pageview_url);
方案3:大表场景用临时表方案
如果单表数据量超过百万级,可以用教程提到的临时表方案,拆分执行逻辑降低内存占用:
-- 第一步:创建临时表存储符合条件的会话首访页面ID CREATE TEMPORARY TABLE first_pageview_temp SELECT website_session_id, MIN(website_pageview_id) AS first_pageview_id FROM website_pageviews WHERE created_at < '2012-06-14' GROUP BY website_session_id; -- 第二步:关联原表查询落地页URL SELECT p.website_session_id, p.website_pageview_id, p.pageview_url FROM website_pageviews p INNER JOIN first_pageview_temp t ON p.website_pageview_id = t.first_pageview_id;
内容的提问来源于stack exchange,提问作者ZON
相关产品推荐
相关产品推荐

