我有两个简单的问题:
SELECT count(*) FROM table1 WHERE cond1=exp1 AND cond2=exp2
返回行数。例如47。SELECT count(*),some_column FROM table1 WHERE cond1=exp1 AND cond2=exp2
从some_column返回行数(例如47行)和任意值,其速度是第一个查询的两倍!我在服务器上直接测试了它,当然是通过GUI (HeidiSQL)测试的,结果是一样的,查询2的速度是原来的两倍!知道为什么会这样吗?
我在Win server 2012上使用MySQL服务器5.6.21和Apache/PHP5.3。
更新1:
CREATE TABLE `programs` (
`tvp_id` INT(11) NOT NULL AUTO_INCREMENT,
`tvp_time` TIME NOT NULL DEFAULT '00:00:00',
`tvp_time_end` TIME NOT NULL DEFAULT '00:00:00',
`tvp_date` DATE NOT NULL DEFAULT '0000-00-00',
`tvp_title` VARCHAR(200) NOT NULL,
`tvp_channel` INT(11) NOT NULL DEFAULT '0',
`tvp_type` VARCHAR(20) NOT NULL,
`tvp_description` TEXT NOT NULL',
... more and more columns ...
PRIMARY KEY (`tvp_id`),
INDEX `tvp_date` (`tvp_date`),
INDEX `tvp_channel` (`tvp_channel`),
INDEX `tvp_time` (`tvp_time`),
)
ENGINE=MyISAM我清除缓存并多次运行查询--结果是相同的--查询速度要快2倍。
对我的表的特定查询如下:
1. SELECT COUNT(*) FROM programs WHERE (tvp_chanel = value_channel) AND (tvp_date = value_date)或
2. SELECT COUNT(*), tvp_type FROM programs WHERE (tvp_channel = value_channel) AND (tvp_date = value_date)所以WHERE子句中的两个列都是带有索引的列。
我试着解释一下这个查询:
1. "id" "select_type" "table" "type" "possible_keys" "key" "key_len" "ref" "rows" "Extra"
"1" "SIMPLE" "programs" "index_merge" "tvp_date,tvp_channel" "tvp_channel,tvp_date" "4,3" \N "15" "Using intersect(tvp_channel,tvp_date); Using where; Using index"2. "id" "select_type" "table" "type" "possible_keys" "key" "key_len" "ref" "rows" "Extra"
"1" "SIMPLE" "programms" "index_merge" "tvp_date,tvp_channel" "tvp_channel,tvp_date" "4,3" \N "15" "Using intersect(tvp_channel,tvp_date); Using where"不同的是在查询中“使用索引”。那么,为什么查询速度较慢呢?
发布于 2019-10-10 21:06:46
不是直接回答你的问题,但为什么不使用计数(1)而不是计数(*)?正如Patrick所建议的,在优化器选择要依赖的列时可能会出现问题。如果使用count(1),则不涉及任何列,只需对返回的记录数进行计数。
发布于 2014-12-01 02:49:42
这可能是一次黑暗中的尝试,但我可以想象,优化器可能不明智地选择完全扫描非聚集索引(可能是主键),而第二个优化器则以某种方式激励优化器完全扫描聚集索引(AKA,只查看存储的行)。
也可能不是。在任何DBMS中,谁能知道优化器的方式?
发布于 2014-12-01 03:22:59
我注意到你的桌子引擎是myisam,你为什么要用它?无论如何,您是否有可能将其转换为innodb并查看这两个查询发生了什么?
顺便说一句,这可能与您的问题无关,index merge并不总是好的,在某些情况下甚至可能是性能杀手。下面是一个例子:http://www.percona.com/blog/2012/12/14/the-optimization-that-often-isnt-index-merge-intersection/
关键是,许多单列索引可能是一个危险的迹象。例如,如果您的查询是
SELECT COUNT(*) FROM programs WHERE (tvp_chanel = value_channel) AND (tvp_date = value_date),
(tvp_chanel, tvp_date)上的索引是覆盖指数,这是最理想的情况。(是的,我知道这可能是无关紧要的,只是忍不住要提一下)
为了以防万一,在测试时使用select sql_no_cache禁用查询缓存。
https://stackoverflow.com/questions/26999869
复制相似问题