2011-07-17 100 views
1

查詢MySQL的 - where子句比全掃描

Select id from jobs; 

| 55966 | 
| 55971 | 
+-------+ 
10705 rows in set (0.00 sec) 

查詢乙

Select id from jobs where status = 0; 
| 55966 | 
| 55971 | 
+-------+ 
7933 rows in set (**20.22 sec**) 

較慢有上狀態的指標。

mysql> explain select id from jobs where status = 0; 
+----+-------------+-------+------+---------------+------+---------+------+-------+-------------+ 
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra  | 
+----+-------------+-------+------+---------------+------+---------+------+-------+-------------+ 
| 1 | SIMPLE  | jobs | ALL | status  | NULL | NULL | NULL | 10705 | Using where | 
+----+-------------+-------+------+---------------+------+---------+------+-------+-------------+ 
1 row in set (0.01 sec) 


mysql> show profile for query 1; 
+--------------------------------+-----------+ 
| Status       | Duration | 
+--------------------------------+-----------+ 
| starting      | 0.000023 | 
| checking query cache for query | 0.000039 | 
| checking permissions   | 0.000006 | 
| Opening tables     | 0.000008 | 
| System lock     | 0.000004 | 
| Table lock      | 0.000016 | 
| init       | 0.000021 | 
| optimizing      | 0.000007 | 
| statistics      | 0.000904 | 
| preparing      | 0.000023 | 
| executing      | 0.000003 | 
| Sending data     | 19.751547 | 
| end       | 0.000009 | 
| query end      | 0.000002 | 
| freeing items     | 0.001561 | 
| storing result in query cache | 0.000122 | 
| logging slow query    | 0.000002 | 
| logging slow query    | 0.000002 | 
| cleaning up     | 0.000003 | 
+--------------------------------+-----------+ 

mysql> show index from jobs; 
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+ 
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | 
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+ 

| jobs |   1 | status |   1 | status  | A   |   6 |  NULL | NULL | YES | BTREE  |   | 
| jobs |   1 | date  |   1 | dateinit | A   |  1784 |  NULL | NULL | YES | BTREE  |   | 
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+ 
10 rows in set (0.02 sec) 

我不明白爲什麼查詢B需要20秒,而查詢A需要0。 「狀態」索引。 prod和dev的結果相同。服務器。

+0

0.00秒聽起來像查詢被緩存。你是否在測試之間刷新緩存? –

+0

RESET QUERY CACHE;從nsync.jobs中選擇ID; - > 10705行(0.00秒)。還是同樣的結果:?( – Benjamin

+0

嗯如果所有的時間「發送數據」,什麼是查詢的時候,你問的只是一個'COUNT()'匹配查詢,而不是行的 –

回答

1

嘗試改變指數兩列(status, id)

在我看來,你沒有任何指數ID

ANSI standard(尋找「Scalar expressions 125」)指出,COUNT(*)給行數的表格:它打算從一開始就進行優化。

如果指定COUNT(*),那麼結果是T.

的基數這就是爲什麼COUNT(*)是遠遠快則COUNT(id)COUNT(*)可以使用status索引。 COUNT(id)不會使用這個指數並沒有其他有效的索引

什麼是聚簇索引,什麼是PK?你有(即使相同的指數),對嗎?

+0

這就是它。我有一個唯一的ID索引..但沒有狀態和ID索引...現在我明白了差異。它的工作就像一個魅力。非常感謝。 – Benjamin

+0

@Benjamin:ID是聚集索引/ PK?如果是,那麼你不應該需要組合索引,因爲如果索引的結構如何, – gbn

+0

是的,它是主鍵。什麼是「聚集索引」 – Benjamin

1

0.00秒聽起來像查詢可能是緩存。話雖這麼說,對於表的id查詢可直接從主鍵索引來回答(即沒有在表中的數據看,在所有!),同時用WHERE子句的查詢需要的數據庫,以實際讀取的行。

+0

從工作中選擇國家; 10705結果在0秒 – Benjamin

+0

從工作中選擇國家狀態= 0; 7933結果爲20秒 – Benjamin

0

status上有一個索引,但是一旦MySQL確定哪些行有status = 0,就有一個調用,爲每一行找到它的id。如果你create index idx_jobs_status_id on jobs (status, id);我預測20秒鐘會下降。

+0

就是這樣!現在工作,非常感謝,現在我明白了爲什麼索引需要多個值... – Benjamin