SELECT count(*)比MySQL中的SELECT count(*),some_column慢两倍

时间:2014-11-18 17:04:28

标签: mysql sql performance count myisam

我有两个简单的查询:

  1. SELECT count(*) FROM table1 WHERE cond1=exp1 AND cond2=exp2

    返回行数。例如47。

  2. SELECT count(*),some_column FROM table1 WHERE cond1=exp1 AND cond2=exp2

    返回行数,例如47,来自some_column的任意值,它的速度是第一个查询的两倍!我直接在服务器上测试它,当然是在GUI(HeidiSQL)上,结果是一样的,查询2的速度是原来的两倍!

  3. 知道为什么会这样吗?

    我在Win Server 2012上使用MySQL服务器5.6.21和Apache / PHP 5.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)查询速度提高了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子句中的两列都是带INDEX的列。

    我为这些查询尝试EXPLAIN:

    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"
    

    1)查询中的“使用索引”不同。那么为什么1)查询速度较慢?

3 个答案:

答案 0 :(得分:1)

不是您问题的直接答案,但是为什么不使用count(1)而不是count(*)?正如帕特里克(Patrick)所建议的那样,优化器选择要依赖的列可能会出现问题。如果使用count(1),则不涉及任何列,而只是返回的记录数的计数。

答案 1 :(得分:0)

这可能是在黑暗中拍摄的,但我可以想象优化器可能不明智地选择完全扫描非聚集索引(可能是主键),而第二种方式促使优化器完全扫描聚簇索引(AKA根本没有索引,只是在存储时查看行。)

或许不是。谁能告诉任何DBMS中优化器的方法?

答案 2 :(得分:0)

我注意到你的桌面引擎是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禁用查询缓存