【问题标题】:Select query with subselects slows down when constrained受约束时,带有子选择的选择查询会变慢
【发布时间】:2015-11-19 07:03:15
【问题描述】:

这个查询运行得非常快:

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`)
);

我对优化以及子选择背后的理论略知一二——但不知道为什么会产生如此大的影响,也不知道如何解决。

【问题讨论】:

    标签: mysql sql sqlite correlated-subquery


    【解决方案1】:

    您完全可以避免使用相关子查询。使用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
    

    【讨论】:

    • 太棒了 - 谢谢 :) - 我最初是使用 MySQL IF 编写的 - 但后来在 Sqlite 中使用相同的查询时遇到了问题 - 没有意识到 CASE 是标准的
    • @HorusKol CASE 是 ANSI 标准
    • 好吧 - 当然让我的事情变得更容易 - 我在同一个查询中还有另外两个不同条件的计数 X)
    猜你喜欢
    • 2014-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-23
    • 1970-01-01
    • 2021-06-19
    • 1970-01-01
    • 2014-09-17
    相关资源
    最近更新 更多