2012-01-30 91 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