2012-06-15 54 views
2

我有一個超過900萬行的表。我有一個SELECT查詢,我正在使用索引。以下是查詢:MySQL對同一查詢的索引使用不一致

SELECT `username`,`id` 
FROM `04c1Tg0M` 
WHERE `id` > 9259466 
AND `tried` = 0 
LIMIT 1; 

該查詢執行速度非常快(0.00秒)。下面是該查詢的解釋:

+----+-------------+----------+-------+-----------------+---------+---------+------+-------+-------------+ 
| id | select_type | table | type | possible_keys | key  | key_len | ref | rows | Extra  | 
+----+-------------+----------+-------+-----------------+---------+---------+------+-------+-------------+ 
| 1 | SIMPLE  | 04c1Tg0M | range | PRIMARY,triedex | PRIMARY | 4  | NULL | 10822 | Using where | 
+----+-------------+----------+-------+-----------------+---------+---------+------+-------+-------------+ 

現在這裏除了我要去ID更改爲6259466相同的查詢:

SELECT `username`,`id` 
FROM `04c1Tg0M` 
WHERE `id` > 5986551 
AND `tried` = 0 
LIMIT 1; 

該查詢了4.78秒完成。這就是問題。以下是對該查詢的解釋:

+----+-------------+----------+------+-----------------+---------+---------+-------+---------+-------------+ 
| id | select_type | table | type | possible_keys | key  | key_len | ref | rows | Extra  | 
+----+-------------+----------+------+-----------------+---------+---------+-------+---------+-------------+ 
| 1 | SIMPLE  | 04c1Tg0M | ref | PRIMARY,triedex | triedex | 2  | const | 9275107 | Using where | 
+----+-------------+----------+------+-----------------+---------+---------+-------+---------+-------------+ 

這裏發生了什麼,如何解決?這裏是我的指標:

+----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+ 
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | 
+----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+ 
| 04c1Tg0M |   0 | PRIMARY |   1 | id   | A   |  9275093 |  NULL | NULL |  | BTREE  |   | 
| 04c1Tg0M |   1 | pdex  |   1 | username | A   |  9275093 |  NULL | NULL |  | BTREE  |   | 
| 04c1Tg0M |   1 | pdex  |   2 | id   | A   |  9275093 |  NULL | NULL |  | BTREE  |   | 
| 04c1Tg0M |   1 | pdex  |   3 | tried  | A   |  9275093 |  NULL | NULL | YES | BTREE  |   | 
| 04c1Tg0M |   1 | triedex |   1 | tried  | A   |   0 |  NULL | NULL | YES | BTREE  |   | 
| 04c1Tg0M |   1 | triedex |   2 | id   | A   |  9275093 |  NULL | NULL |  | BTREE  |   | 
+----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+ 

這裏是我的表結構:

| 04c1Tg0M | CREATE TABLE `04c1Tg0M` (
`id` int(20) NOT NULL AUTO_INCREMENT, 
`username` varchar(50) NOT NULL, 
`tried` tinyint(1) DEFAULT '0', 
PRIMARY KEY (`id`), 
KEY `pdex` (`username`,`id`,`tried`), 
KEY `triedex` (`tried`,`id`) 
) ENGINE=MyISAM AUTO_INCREMENT=9275108 DEFAULT CHARSET=utf8 | 
+0

你是否一個接一個地運行這些查詢? – Dancrumb

+0

彼此在幾秒鐘之內 – xendi

+2

您是否已經意識到您正在檢查3M行更多(支持ID是相關的)比在第一個查詢中?結果中只有一行,但您正在檢查更多的行。 – Ander2

回答

1

第一個SQL返回10822行,而第二個返回9275107行!

在第二個查詢中使用主鍵「id」索引並不是很有用,因爲無論如何您都必須執行全表掃描。

MySQL的基於成本的優化器認爲,在第二個查詢的情況下,最好使用'已嘗試'的索引。

如果您必須執行全表掃描,則最好不要使用索引,因爲索引構成額外的磁盤讀取。

您可以在查詢中使用「使用索引」或「強制索引」來向優化器提示是否使用索引。

還通過定期分析您的表來更新統計數據,以便基於成本的優化器正常工作。

+0

強制索引或索引暗示一定會做的工作 –