2012-07-12 83 views
1

我有一個讓他們之間的外鍵約束連接表:MySQL的性能

Table event 
mysql> describe event; 
+------------+------------------+------+-----+---------+-------+ 
| Field  | Type    | Null | Key | Default | Extra | 
+------------+------------------+------+-----+---------+-------+ 
| sid  | int(10) unsigned | NO | PRI | NULL |  | 
| cid  | int(10) unsigned | NO | PRI | NULL |  | 
| signature | int(10) unsigned | NO | MUL | NULL |  | 
| timestamp | datetime   | NO | MUL | NULL |  | 
| is_deleted | tinyint(1)  | NO | MUL | 0  |  | 
+------------+------------------+------+-----+---------+-------+ 
5 rows in set (0.00 sec) 

Table signature 
mysql> describe signature; 
+--------------+------------------+------+-----+---------+----------------+ 
| Field  | Type    | Null | Key | Default | Extra   | 
+--------------+------------------+------+-----+---------+----------------+ 
| sig_id  | int(10) unsigned | NO | PRI | NULL | auto_increment | 
| sig_name  | varchar(255)  | NO | MUL | NULL |    | 
| sig_class_id | int(10) unsigned | NO | MUL | NULL |    | 
| sig_priority | int(10) unsigned | YES |  | NULL |    | 
| sig_rev  | int(10) unsigned | YES |  | NULL |    | 
| sig_sid  | int(10) unsigned | YES |  | NULL |    | 
| sig_gid  | int(10) unsigned | YES |  | NULL |    | 
+--------------+------------------+------+-----+---------+----------------+ 
7 rows in set (0.00 sec) 

event.signature是一個外鍵和鏈接到signature.sig_id兩個表。兩者都有指標以及

表事件是大的(比如說1M記錄),而表簽名會比較小(幾千元最多)

訪問任何簽字註冊查詢屬性需要很長的時間來執行。一看解釋

mysql> explain select event.sid,event.cid,signature.sig_name from event join signature on signature.sig_id=event.signature; 
+----+-------------+-----------+------+--------------------------------+-----------------------+---------+-------------------------+------+--------------------------+ 
| id | select_type | table  | type | possible_keys     | key     | key_len | ref      | rows | Extra     | 
+----+-------------+-----------+------+--------------------------------+-----------------------+---------+-------------------------+------+--------------------------+ 
| 1 | SIMPLE  | signature | ALL | PRIMARY,index_signature_sig_id | NULL     | NULL | NULL     | 127 |       | 
| 1 | SIMPLE  | event  | ref | index_event_signature   | index_event_signature | 5  | snorby.signature.sig_id | 68 | Using where; Using index | 
+----+-------------+-----------+------+--------------------------------+-----------------------+---------+-------------------------+------+--------------------------+ 
2 rows in set (0.00 sec) 

雖然如果沒有簽名屬性被訪問

如果簽名屬性查詢它完全掃描ALL
mysql> explain select event.sid,event.cid from event join signature on signature.sig_id=event.signature; 
+----+-------------+-----------+-------+--------------------------------+------------------------+---------+-------------------------+------+--------------------------+ 
| id | select_type | table  | type | possible_keys     | key     | key_len | ref      | rows | Extra     | 
+----+-------------+-----------+-------+--------------------------------+------------------------+---------+-------------------------+------+--------------------------+ 
| 1 | SIMPLE  | signature | index | PRIMARY,index_signature_sig_id | index_signature_sig_id | 4  | NULL     | 127 | Using index    | 
| 1 | SIMPLE  | event  | ref | index_event_signature   | index_event_signature | 5  | snorby.signature.sig_id | 68 | Using where; Using index | 
+----+-------------+-----------+-------+--------------------------------+------------------------+---------+-------------------------+------+--------------------------+ 
2 rows in set (0.00 sec) 

可以看出連接類型。

是否有可能重寫查詢更快?我問這個,因爲這是多個表的一部分加入,與簽名加入事件是減緩查詢極大

的瓶頸,我用52年5月1日MySQL和SQLAlchemy的0.7.8作爲ORM

回答

1

你查詢確實按定義需要全面掃描。

也就是說,你沒有給出過濾條件。例如,沒有... WHERE sig_rev = 17

因此,這裏沒有多少改進。 MySQL選擇一個表開始,進行全面掃描,每行讀取第二個表中的匹配行。

所以掃描是必不可少的。但是你可以把它變成索引掃描而不是表掃描。我假設您只有signature列和僅有sig_id列的索引。

你可以做的是對sig_id, sig_name創建一個額外的指標,如:

ALTER TABLE signature ADD UNIQUE INDEX(sig_id, sig_name); 

該指數是通過定義獨一無二的,因爲它比PRIMARY KEY更廣泛的,但這是一點之外。

您現在可能獲得的執行計劃類似於您發佈的第二個示例:在signature上進行索引掃描,然後是對事件的索引查找。

確保比較並驗證您是否在此特定查詢上獲得了性能提升。檢查新索引是否損壞INSERT性能等。

祝你好運。

+0

我曾經這麼認爲......但即使在sig_id上添加唯一索引,sig_name(255)也不會更改執行計劃。它在使用的密鑰中仍然是NULL。我想我必須重寫代碼並確保獲得所有其他屬性,然後僅查詢簽名以獲取特定的簽名標識 – RedBaron 2012-07-12 11:28:32

+0

然後,MySQL可能不會批准使用索引,因爲您的表可能不夠大。 在查詢中嘗試'FORCE INDEX(the_new_index_name)'... – 2012-07-12 12:06:55

+0

其實問題是我在訂購基於非索引列的查詢。但我忘了提及它。 – RedBaron 2012-07-13 05:49:49