2012-01-30 57 views
0

可为什么MySQL是不是在下面的查询MySQL索引的问题

SELECT `Slugs`.`slug` FROM `slugs` AS `Slugs` 
WHERE `Slugs`.`country_id` = 1 AND `Slugs`.`expired` = 0  
LIMIT 308400,300 

我已经创造了在where子句

表结构所指向的两列的cmposite指数使用正确的索引有人告诉我为表slugs

CREATE TABLE IF NOT EXISTS `slugs` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `slug` varchar(255) NOT NULL, 
    `post_fields` text NOT NULL, 
    `slugdata` text NOT NULL, 
    `updated_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 
    `country_id` int(11) NOT NULL DEFAULT '1', 
    `expired` int(1) NOT NULL DEFAULT '0', 
    PRIMARY KEY (`id`), 
    UNIQUE KEY `slug_2` (`slug`,`country_id`), 
    KEY `updated_date` (`updated_date`), 
    KEY `country_id` (`country_id`), 
    KEY `slug` (`slug`), 
    KEY `expired` (`expired`), 
    KEY `country_id_2` (`country_id`,`expired`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1612485 ; 

指标:

Keyname  Type Unique Packed Field  Cardinality  Collation Null Comment 
PRIMARY  BTREE Yes  No  id    1406994  A  
slug_2  BTREE Yes  No  slug    1406994  A  
            country_id  1406994  A 
updated_date BTREE No  No  updated_date   21  A  
country_id BTREE No  No  country_id   21  A  
slug   BTREE No  No  slug    1406994  A  
expired  BTREE No  No  expired    21  A  
country_id_2 BTREE No  No  country_id   21  A  
            expired    21  A 

输出解释

id select_type  table type possible_keys key  key_len  ref  rows Extra 
1 SIMPLE Slugs ref  country_id,expired,country_id_2  country_id 4 const 670284 Using where 
+0

什么是根据你的正确索引?你的索引也可能*基数很低,难怪MySQL检查这么多行。 – 2012-01-30 10:53:41

回答

1

你是什么意思它不使用正确的索引?

country_id和country_id_2的基数非常低,实际上两个索引都相同 - 因此使用基于2列的索引没有任何好处。这意味着很少有记录过期<> 0。

但是为什么过期指数的基数也是21?

什么是从输出:

SELECT 'expired' AS fld 
, COUNT(*) AS distinct_values 
, AVG(n) AS rows 
FROM 
(SELECT expired AS v 
, COUNT(*) AS n 
FROM slugs 
GROUP BY expired) ilv1 
UNION 
SELECT 'country_id', 
, COUNT(*) AS distinct_values 
, AVG(n) AS rows 
FROM 
(SELECT country_id AS v 
, COUNT(*) AS n 
FROM slugs 
GROUP BY country_id) ilv2 
    SELECT 'expired:country_id', 
, COUNT(*) AS distinct_values 
, AVG(n) AS rows 
FROM 
(SELECT CONCAT(expired, country_id) AS v 
, COUNT(*) AS n 
FROM slugs 
GROUP BY CONCAT(expired, country_id)) ilv3; 
+0

过期只有两个值0,1。在表中只有11000条记录过期= 1。我可以尝试运行你的查询,但是它会把什么类型的负载放到我的机器上,不要忘记我在表 – 2012-01-30 12:48:47

+0

表中有几百万行真的吗? MysQL认为你只有140万行。丢失愚蠢的索引(country_id,slug和过期),并分析表(是的,它会在你运行时受到伤害) – symcbean 2012-01-30 14:13:03

+0

嗨,我放弃了额外的indixes--即 - country,expired,slugs.Now Mysql似乎在使用正确的索引,但似乎仍然遍历了很多行。写这个查询的最好方法是什么? – 2012-01-31 07:14:11