这是mysql的错误吗?两个命令几乎相同,但复杂的命令比简单快

时间:2013-04-02 03:44:24

标签: mysql

mysql> desc ads_common;
+--------------+-----------------------+------+-----+-------------------+----------------+
| Field        | Type                  | Null | Key | Default           | Extra          |
+--------------+-----------------------+------+-----+-------------------+----------------+
| ads_id       | bigint(20) unsigned   | NO   | PRI | NULL              | auto_increment |
| user_id      | bigint(20) unsigned   | NO   | MUL | NULL              |                |
| website_type | enum('group','user')  | NO   | MUL | NULL              |                |
| website_id   | bigint(20) unsigned   | NO   |     | NULL              |                |
| subgroup_id  | bigint(20) unsigned   | NO   |     | NULL              |                |
| country_id   | smallint(5) unsigned  | NO   | MUL | NULL              |                |
| type_id      | int(10) unsigned      | NO   | MUL | NULL              |                |
| phone        | int(11)               | NO   |     | NULL              |                |
| mobile_phone | int(10) unsigned      | NO   |     | NULL              |                |
| cat_id       | int(10) unsigned      | NO   | MUL | NULL              |                |
| brand_id     | mediumint(8) unsigned | NO   | MUL | NULL              |                |
| model_id     | mediumint(8) unsigned | NO   | MUL | NULL              |                |
| area_id      | int(10) unsigned      | NO   | MUL | NULL              |                |
| is_offering  | tinyint(1)            | NO   | MUL | 1                 |                |
| price        | int(11)               | NO   | MUL | NULL              |                |
| item_status  | tinyint(3) unsigned   | NO   | MUL | NULL              |                |
| add_time     | timestamp             | NO   | MUL | CURRENT_TIMESTAMP |                |
| question_num | smallint(5) unsigned  | NO   |     | NULL              |                |
| is_stop      | tinyint(1)            | NO   | MUL | 0                 |                |
+--------------+-----------------------+------+-----+-------------------+----------------+

我确实有type_id,country_id,is_top多列索引和type_id单索引。 ads_common表约有180245行。

1.first query command

SELECT c.ads_id FROM ads_common AS c                                
WHERE c.type_id IN (185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241) 
AND c.country_id=226 AND is_stop=0  ORDER BY c.ads_id DESC

找到180,047行,这需要0.0026秒

2.second query command

SELECT c.ads_id FROM ads_common AS c
WHERE c.type_id=187 
AND c.country_id =226 AND is_stop=0 ORDER BY c.ads_id DESC

找到180,044行,这需要0.2335秒

只有不同的两个命令是" type_id IN(..187 ..)"和" type_id = 187",为什么命令2慢于1?

如果命令2改为:

SELECT c.ads_id FROM ads_common AS c
WHERE c.type_id IN (185, 187)
AND c.country_id =226 AND is_stop =0 ORDER BY c.ads_id DESC

找到180,044行,这需要0.0007秒,这样更快。

SELECT c.ads_id FROM ads_common AS c
WHERE c.type_id IN (187)
AND c.country_id =226 AND is_stop =0 ORDER BY c.ads_id DESC

发现180,044行,这需要0.2267秒,这样更快。

所有命令返回几乎相同的行。

1 个答案:

答案 0 :(得分:0)

1.command

SELECT c.ads_id
FROM ads_common AS c                                
WHERE c.type_id=187
AND c.country_id=226 AND is_stop=0  ORDER BY c.ads_id DESC

(总共180,044,查询花了0.2364秒)


    EXPLAIN

    id:1
    select_type:    SIMPLE
    table:c
    type:index_merge
    possible_keys:type_id,country_id,is_stop
    key:is_stop,country_id,type_id
    key_len:1,2,4
    ref:NULL
    rows:22530  
    Extra:Using intersect(is_stop,country_id,type_id); Using...

2.command

SELECT c.ads_id
FROM ads_common AS c                                
WHERE c.type_id IN (0,187)
AND c.country_id=226 AND is_stop=0  ORDER BY c.ads_id DESC

总共180,044,查询耗时0.0010秒


    EXPLAIN

    id:1
    select_type:    SIMPLE
    table:c
    type:ref
    possible_keys:type_id,country_id,is_stop
    key:country_id
    key_len:2
    ref:const
    rows:90122
    Extra:Using where

非常有趣,几乎相同的命令,但获得不同的表现。

最后,我重启mysql并执行命令,每次执行命令前都重启,所以缓存没问题。


command 1 took 1.2358 second "c.type_id=187"
command 2 took 0.05 second "c.type_id IN (0, 187)", you can replace 0 to any number, result the same.

是," c.type_id在(187)"与" c.type_id = 187"相同,但" c.type_id在(187,0)"或" c.type_id in(0,187)"获得更好的表现。