2012-09-20 71 views
2

我有一個SQL語句,看起來像這樣:將在SQL語句中額外的項目導致性能

SELECT colID 
FROM tableName 
WHERE ColDateStart <='$lowerDate' 
AND ColDateStart>='$upperDate' 
AND ColVcamID='$id1' 
AND ColVlviID='$id2' 
AND ColSomeID='$id3'; 

所有在WHERE statment列索引的列。

當我運行它需要一秒鐘。但是,當我運行這個沒有其他Id3時,性能顯着提高(0.03秒)。

當我運行解釋,與otherId3,它使用索引合併使用otherId1和otherId3。但是,當我刪除otherId3時,它使用otherId2的單個索引。

爲什麼添加otherId3會對性能產生影響?

表結構:

+----------------------+-------------+------+-----+---------------------+----------------+ 
| Field    | Type  | Null | Key | Default    | Extra   | 
+----------------------+-------------+------+-----+---------------------+----------------+ 
| ColID    | int(11)  | NO | PRI | NULL    | auto_increment | 
| ColCustID   | int(11)  | NO | MUL | 0     |    | 
| ColCarrID   | int(11)  | NO | MUL | NULL    |    | 
| ColTariID   | int(11)  | NO | MUL | 0     |    | 
| ColCarrierRef  | varchar(30) | NO | MUL |      |    | 
| ColNumbID   | int(11)  | NO | MUL | 0     |    | 
| ColVlviID   | int(11)  | NO | MUL | NULL    |    | 
| ColVcamID   | int(11)  | NO | MUL | NULL    |    | 
| ColSomeID   | int(11)  | NO | MUL | NULL    |    | 
| ColVlnsID   | int(11)  | NO | MUL | NULL    |    | 
| ColNGNumber   | varchar(12) | NO |  |      |    | 
| ColOrigNumber  | varchar(16) | NO | MUL | NULL    |    | 
| ColCLIRestrictedFlag | int(2)  | NO |  | NULL    |    | 
| ColOrigLocality  | varchar(11) | NO | MUL |      |    | 
| ColOrigAreaCode  | varchar(11) | NO | MUL |      |    | 
| ColTermNumber  | varchar(16) | NO | MUL | NULL    |    | 
| ColBatchNumber  | varchar(10) | NO |  |      |    | 
| ColDateStart   | date  | NO | MUL | 0000-00-00   |    | 
| ColDateClear   | date  | NO |  | 0000-00-00   |    | 
| ColTimeStart   | time  | NO |  | 00:00:00   |    | 
| ColTimeClear   | time  | NO |  | 00:00:00   |    | 
| ColCallLength  | time  | NO |  | 00:00:00   |    | 
| ColRingLength  | time  | NO |  | 00:00:00   |    | 
| ColEffectiveFlag  | smallint(1) | NO | MUL | NULL    |    | 
| ColUnansweredFlag | smallint(1) | NO | MUL | NULL    |    | 
| ColEngagedFlag  | smallint(1) | NO |  | NULL    |    | 
| ColRecID    | int(11)  | NO | MUL | NULL    |    | 
| ColCreatedUserID  | int(11)  | NO |  | 0     |    | 
| ColCreatedDatetime | datetime | NO | MUL | 0000-00-00 00:00:00 |    | 
| ColDirection   | int(1)  | NO | MUL | NULL    |    | 
+----------------------+-------------+------+-----+---------------------+----------------+ 

指標

+-------+------------+-------------------------------+--------------+---------------------+-----------+-------------+----------+--------+------+------------+---------+ 
| Table | Non_unique | Key_name      | Seq_in_index | Column_name   | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | 
+-------+------------+-------------------------------+--------------+---------------------+-----------+-------------+----------+--------+------+------------+---------+ 
| tableName |   0 | PRIMARY      |   1 | ColID    | A   | 18031283 |  NULL | NULL |  | BTREE  |   | 
| tableName |   1 | idx_ColCustID    |   1 | ColCustID   | A   |  1339 |  NULL | NULL |  | BTREE  |   | 
| tableName |   1 | idx_ColNumbID    |   1 | ColNumbID   | A   |  24366 |  NULL | NULL |  | BTREE  |   | 
| tableName |   1 | idx_colOrigNumber   |   1 | colOrigNumber  | A   |  4507820 |  NULL | NULL |  | BTREE  |   | 
| tableName |   1 | idx_colOrigLocality   |   1 | colOrigLocality | A   |  36873 |  NULL | NULL |  | BTREE  |   | 
| tableName |   1 | idx_colOrigAreaCode   |   1 | colOrigAreaCode | A   |   696 |  NULL | NULL |  | BTREE  |   | 
| tableName |   1 | idx_colTermNumber   |   1 | colTermNumber  | A   |  137643 |  NULL | NULL |  | BTREE  |   | 
| tableName |   1 | idx_colDateStart    |   1 | colDateStart  | A   |  3639 |  NULL | NULL |  | BTREE  |   | 
| tableName |   1 | idx_colEffectiveFlag   |   1 | colEffectiveFlag | A   |   2 |  NULL | NULL |  | BTREE  |   | 
| tableName |   1 | idx_colUnansweredFlag  |   1 | colUnansweredFlag | A   |   2 |  NULL | NULL |  | BTREE  |   | 
| tableName |   1 | idx_colEngagedFlag   |   1 | colUnansweredFlag | A   |   2 |  NULL | NULL |  | BTREE  |   | 
| tableName |   1 | idx_colTariID    |   1 | colTariID   | A   |   91 |  NULL | NULL |  | BTREE  |   | 
| tableName |   1 | idx_CustID_DateStart   |   1 | colCustID   | A   |  1339 |  NULL | NULL |  | BTREE  |   | 
| tableName |   1 | idx_CustID_DateStart   |   2 | colDateStart  | A   |  693510 |  NULL | NULL |  | BTREE  |   | 
| tableName |   1 | idx_NumbID_DateStart   |   1 | colNumbID   | A   |  24366 |  NULL | NULL |  | BTREE  |   | 
| tableName |   1 | idx_NumbID_DateStart   |   2 | colDateStart  | A   |  4507820 |  NULL | NULL |  | BTREE  |   | 
| tableName |   1 | idx_colRecID     |   1 | colRecID   | A   |  214658 |  NULL | NULL |  | BTREE  |   | 
| tableName |   1 | idx_colCarrierRef   |   1 | colCarrierRef  | A   |  6010427 |  NULL | NULL |  | BTREE  |   | 
| tableName |   1 | idx_colCustID_colTermNumber |   1 | colCustID   | A   |  1339 |  NULL | NULL |  | BTREE  |   | 
| tableName |   1 | idx_colCustID_colTermNumber |   2 | colTermNumber  | A   |  143105 |  NULL | NULL |  | BTREE  |   | 
| tableName |   1 | idx_colCreatedDatetime  |   1 | colCreatedDatetime | A   |  474507 |  NULL | NULL |  | BTREE  |   | 
| tableName |   1 | idx_colDirection    |   1 | colDirection  | A   |   2 |  NULL | NULL |  | BTREE  |   | 
| tableName |   1 | idx_colVlviID    |   1 | colVlviID   | A   |  4133 |  NULL | NULL |  | BTREE  |   | 
| tableName |   1 | idx_colSomeID    |   1 | colSomeID   | A   |   10 |  NULL | NULL |  | BTREE  |   | 
| tableName |   1 | idx_colVcamID    |   1 | colVcamID   | A   |   7 |  NULL | NULL |  | BTREE  |   | 
| tableName |   1 | idx_colVlnsID    |   1 | colVlnsID   | A   |   18 |  NULL | NULL |  | BTREE  |   | 
| tableName |   1 | idx_colCarrID    |   1 | colCarrID   | A   |   4 |  NULL | NULL |  | BTREE  |   | 
+-------+------------+-------------------------------+--------------+---------------------+-----------+-------------+----------+--------+------+------------+---------+ 

回答

1

首先,你有太多可能索引。大多數這些指標可能毫無意義。如果您沒有使用WHERE標準,JOIN或ORDERing的特定索引,請將其刪除,因爲它只會減慢速度。

接下來,爲您的查詢指定總是包含1x DATE和2x INT列的查詢的3列。 DATE列應該是第一個,因爲日期範圍在索引上非常快,然後是兩個INT。這給出了以下3列索引

CREATE INDEX searchIndex 
ON tableName (ColDateStart,ColVlviID,ColVcamID) 
USING BTREE; 

更多信息的起點上可以在這裏找到:http://dev.mysql.com/doc/refman/5.0/en/multiple-column-indexes.html

我下令列這樣故意。 ColDateStart用於日期範圍篩選,其次是基數降序的其他列。我選擇ColVlviID作爲第二列,因爲它的基數爲4133,而ColVcamID的基數爲7.這將允許MySQL更有效地減少匹配行。

現在,假設colSomeID是最後一列,我可能反而做以下

CREATE INDEX searchIndex_someID 
ON tableName (ColDateStart,ColVlviID,ColVcamID,ColSomeID) 
USING BTREE; 

這3列的索引可以幫助MySQL的檢查,去年前ID踏踏實實適用的數據集。如果您通常在另一個特定的INT列中進行篩選,那麼您可以在結尾添加第四列到該索引。

順便說一句,你可能要考慮假定您正在執行查詢之前消毒變量以下,而不是dateCol標準

SELECT colID 
FROM tableName 
WHERE ColDateStart BETWEEN DATE('$lowerDate') AND DATE('$upperDate') 
AND ColVcamID=$id1 
AND ColVlviID=$id2 
AND ColSomeID=$id3 

以上所有課程。我已經從$ idx變量中刪除了引號,因爲它們應該是數字,因此不需要作爲字符串輸入。

+0

本表總共有30列 - 爲了簡單起見,我已將它剪斷。 – mh1

+0

這個SQL用於一組報告中,otherId3可能不會一直存在,有時候它只會是dateCol,otherId1和otherId2,有時otherId3可能存在或其他Id4。無論身在何處,它們都是單一索引。 – mh1

+0

根據新信息更新我的答案。你確實不需要那麼多的索引,我敢肯定;)它只是混淆MySQL優化器,更不用說減慢INSERT/UPDATE等 –

0
SELECT id 
FROM tableName FORCE INDEX(`idx_otherId2`) 
WHERE dateCol <='$lowerDate' 
AND dateCol>='$upperDate' 
AND otherId1='$id1' 
AND otherId2='$id2' 
AND otherId3='$id3'; 
+0

當我使用FORCE INDEX時,這會提高性能,問題是我不明白爲什麼將otherId3添加到where語句會改變所用索引的方式。 – mh1