选择带有子选择的查询在受约束时减慢速度

时间:2015-11-19 07:03:15

标签: mysql sql sqlite correlated-subquery

此查询运行速度非常快:

select mainsearch.product,
(select count(id) from search_log 
    where search_log.hits > 0 
    and search_log.`time` between '2015-09-01 00:00:00' and '2015-09-01 23:59:59' 
    and mainsearch.product = search_log.product
) as success
from search_log as mainsearch
group by mainsearch.product;

这个查询需要永远:

select mainsearch.product,
(select count(id) from search_log 
    where search_log.hits > 0 
    and search_log.`time` between '2015-09-01 00:00:00' and '2015-09-01 23:59:59' 
    and mainsearch.product = search_log.product
) as success
from search_log as mainsearch
where mainsearch.`time` between '2015-09-01 00:00:00' and '2015-09-01 23:59:59' 
group by mainsearch.product;

这是表格规范:

CREATE TABLE `search_log` (
    `id` int(11) NOT NULL AUTO_INCREMENT,
    `query` text NOT NULL,
    `hits` mediumint(9) NOT NULL DEFAULT '0',
    `time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    `product` varchar(16) DEFAULT NULL,
    PRIMARY KEY (`id`),
    KEY `time_index` (`time`),
    KEY `searchlog_product` (`product`)
);

我对优化以及子选择背后的理论有所了解 - 但无法弄清楚为什么会产生这样的影响,也不知道如何解决它。

1 个答案:

答案 0 :(得分:4)

您可以完全避免使用相关子查询。使用CASE WHEN

select 
   mainsearch.product,
   COUNT(CASE WHEN hits > 0 THEN 1 ELSE NULL END) AS success
from search_log as mainsearch
where mainsearch.`time` between '2015-09-01 00:00:00' and '2015-09-01 23:59:59' 
group by mainsearch.product;

你也可以稍微调整它ELSE

COUNT(CASE WHEN hits > 0 THEN 1 END) AS success

甚至更进一步使用(适用于MySQL):

SUM(hits > 0) AS success