2012-06-15 48 views
4

我有一個超過900萬行的非常大的表,在我的軟件中,我需要快速在循環中選擇查詢。問題是查詢需要將近4秒才能完成。下面是查詢之一(他們是在所有相似,它們都具有相同的WHERE子句是減緩下來。MySQL如何加快此SELECT查詢?

SELECT MIN(id) 
FROM `04c1Tg0M` 
WHERE `tried` = 0; 

我使用的嘗試列的布爾值是1或0下面是從查詢的解釋:

--------+--------------------------+ 
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra     | 
+----+-------------+----------+-------+---------------+------+---------+------+---------+--------------------------+ 
| 1 | SIMPLE  | 04c1Tg0M | index | NULL   | pdex | 158  | NULL | 9275107 | Using where; Using index | 
+----+-------------+----------+-------+---------------+------+---------+------+---------+--------------------------+ 

下面是表結構:

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`) 
) ENGINE=MyISAM AUTO_INCREMENT=9275108 DEFAULT CHARSET=utf8 

這裏是節目東印度的輸出:

| 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   |  9275107 |  NULL | NULL |  | BTREE  |   | 
| 04c1Tg0M |   1 | pdex  |   1 | username | A   |  9275107 |  NULL | NULL |  | BTREE  |   | 
| 04c1Tg0M |   1 | pdex  |   2 | id   | A   |  9275107 |  NULL | NULL |  | BTREE  |   | 
| 04c1Tg0M |   1 | pdex  |   3 | tried  | A   |  9275107 |  NULL | NULL | YES | BTREE  |   | 
+----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+ 

這裏是從查詢有關的輸出:

+---------+ 
| MIN(id) | 
+---------+ 
|  1 | 
+---------+ 
1 row in set (3.76 sec) 

我需要大幅降低了查詢時間。任何幫助是極大的讚賞。

+0

你可以發佈'EXPLAIN SELECT'的輸出嗎?你知道有多少比例的'try = 0'和'tried = 1'嗎? –

回答

6

您應該在(tried, id)上添加索引。

您已經在(username,id,tried)上添加了索引,但是由於tried不是索引中的第一項,因此該索引無法有效用於您所寫的查詢。


How MySQL Uses Indexes手冊頁:

MySQL使用索引這些操作:

  • 要查找特定的索引列key_colMIN()MAX()值。這由預處理器進行了優化,該預處理器檢查您是否在索引中的key_col之前發生的所有關鍵部分上使用了WHERE key_part_N = constant。在這種情況下,MySQL會爲每個MIN()MAX()表達式執行單鍵查找,並用常數替換它。如果所有表達式都用常量替換,則查詢立即返回。例如:

    SELECT MIN(key_part2),MAX(key_part2) FROM tbl_name WHERE key_part1 = 10;

請特別注意的是,WHERE條款必須是指發生之前列要爲其計算MINMAX,這就是爲什麼當前的指數不能有效地使用列。


我需要快速做在一個循環中選擇查詢就可以了

你確定你需要在一個循環來查詢?您是否考慮將循環移入數據庫?也許你真正需要的是一個加入?最好發送一個查詢獲取大量數據的查詢,而不是大量只能獲取少量數據的小型查詢。

+0

我剛添加show index的輸出到我的文章。你可以看看有什麼看起來不對嗎?另外,你建議創建第二個複合索引嗎? – xendi

+0

是索引是改進和加快mysql qureies操作的最佳選擇。 – vimal

+0

@xendi:你沒有說別的索引是什麼。 –

2

tried列中添加索引應加快查詢速度。 MySQL使用索引進行這些操作:

查找特定索引列key_col的MIN()或MAX()值。這通過預處理器進行了優化,該預處理器檢查您是否在索引中的key_col之前發生的所有關鍵部分上使用WHERE key_part_N = constant。在這種情況下,MySQL會爲每個MIN()或MAX()表達式執行單鍵查找,並用常數替換它。如果所有表達式都用常量替換,則查詢立即返回。例如:

SELECT MIN(key_part2),MAX(key_part2)FROM tbl_name WHERE key_part1 = 10;

0

如果在tried列上添加索引,則查詢速度應加快。

您可以使用如下命令

create index tried_ix1 on 04c1Tg0M (tried); 

作爲一個側面說明,如果你是在一個InnoDB表應用索引,也請考慮這個指標是否不應當被羣集。例如,如果您要訪問大量表記錄,可能是按照特定順序(可能是按順序排列),那麼可以考慮根據報告的排序要求創建聚集索引。