Select 带有子选择的查询在受约束时变慢
Select query with subselects slows down when constrained
这个查询运行得相当快:
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;
这是 table 规范:
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`)
);
我对优化和子选择背后的理论略知一二 - 但不明白为什么会产生这样的影响,也不知道如何解决它。
你完全可以避免使用相关子查询。使用 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
这个查询运行得相当快:
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;
这是 table 规范:
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`)
);
我对优化和子选择背后的理论略知一二 - 但不明白为什么会产生这样的影响,也不知道如何解决它。
你完全可以避免使用相关子查询。使用 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