2014-04-06 42 views
2

我有這樣的SQL查詢:在MySQL使用索引並不提高查詢時間

SELECT Frage_ID 
FROM Session_Fragen WHERE 
(
    Userantwort1 = 0 
    AND Userantwort2 = 0 
    AND Userantwort3 = 0 
    AND Userantwort4 = 0 
    AND Userantwort5 = 0 
) AND Session_ID = 17898 
ORDER BY Sessionfrage_ID ASC LIMIT 1; 

在此查詢運行非常緩慢的開始。 我增加了索引來提高速度。 使用指數我喜歡掃描約。 500.000行... 使用索引後,我減少了行大約。 550(取決於結果) 但查詢仍然需要2秒以上。跑步。

我希望任何人對我有任何改進...

坦克很多!


SQL EXPLAIN:

id select_type  table type possible_keys key  key_len  ref  rows Extra 
1 SIMPLE Session_Fragen index Session_Fragen_big_index_2,Session_Fragen_big_inde... PRIMARY  8 NULL 535  Using where 

SHOW指標:

Session_Fragen 0 PRIMARY  1 Sessionfrage_ID  A 626229 NULL NULL  BTREE 
Session_Fragen 1 Frage_ID 1 Frage_ID A 3479 NULL NULL  BTREE 
Session_Fragen 1 Session_Fragen_big_index_2 1 Userantwort1 A 2 NULL NULL  BTREE 
Session_Fragen 1 Session_Fragen_big_index_2 2 Userantwort2 A 3 NULL NULL  BTREE 
Session_Fragen 1 Session_Fragen_big_index_2 3 Userantwort3 A 5 NULL NULL  BTREE 
Session_Fragen 1 Session_Fragen_big_index_2 4 Userantwort4 A 7 NULL NULL  BTREE 
Session_Fragen 1 Session_Fragen_big_index_2 5 Userantwort5 A 9 NULL NULL  BTREE 
Session_Fragen 1 Session_Fragen_big_index 1 Session_ID A 16057 NULL NULL  BTREE 
Session_Fragen 1 Session_Fragen_big_index 2 Frage_ID A 626229 NULL NULL  BTREE 
Session_Fragen 1 Session_Fragen_big_index 3   
Sessionfrage_ID  A 626229 NULL NULL  BTREE 
Session_Fragen 1 Userantwort1 1 Userantwort1 A 2 NULL NULL  BTREE 
Session_Fragen 1 Userantwort2 1 Userantwort2 A 2 NULL NULL  BTREE 
Session_Fragen 1 Userantwort3 1 Userantwort3 A 2 NULL NULL  BTREE 
Session_Fragen 1 Userantwort4 1 Userantwort4 A 2 NULL NULL  BTREE 
Session_Fragen 1 Userantwort5 1 Userantwort5 A 2 NULL NULL  BTREE 
Session_Fragen 1 Session_ID 1 Session_ID A 16057 NULL NULL  BTREE 

表結構:

Session_Fragen CREATE TABLE `Session_Fragen` (
`Sessionfrage_ID` bigint(20) NOT NULL AUTO_INCREMENT, 
`User_ID` int(7) NOT NULL, 
`SF_Timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, 
`Session_ID` int(11) NOT NULL, 
`Frage_ID` int(11) NOT NULL, 
`Userantwort1` tinyint(1) NOT NULL DEFAULT '0', 
`Userantwort2` tinyint(1) NOT NULL DEFAULT '0', 
`Userantwort3` tinyint(1) NOT NULL DEFAULT '0', 
`Userantwort4` tinyint(1) NOT NULL DEFAULT '0', 
`Userantwort5` tinyint(1) NOT NULL DEFAULT '0', 
PRIMARY KEY (`Sessionfrage_ID`), 
KEY `Frage_ID` (`Frage_ID`), 
KEY `Session_Fragen_big_index_2`   (`Userantwort1`,`Userantwort2`,`Userantwort3`,`Userantwort4`,`Userantwort5`), 
KEY `Session_Fragen_big_index` (`Session_ID`,`Frage_ID`,`Sessionfrage_ID`), 
KEY `Userantwort1` (`Userantwort1`), 
KEY `Userantwort2` (`Userantwort2`), 
KEY `Userantwort3` (`Userantwort3`), 
KEY `Userantwort4` (`Userantwort4`), 
KEY `Userantwort5` (`Userantwort5`), 
KEY `Session_ID` (`Session_ID`) 
) ENGINE=MyISAM AUTO_INCREMENT=862095 DEFAULT CHARSET=utf8 
+0

嘗試使用SQL JOIN操作,有時會根據設置操作可以執行比常規更快的WHERE操作 – numX

+0

你或許應該在你的UserantworX列使用NULL,而不是投入虛擬0值。您正在使用「0」來表示「沒有價值」的時候,這正是NULL表示。因爲優化處理空值不必查找零更好的它也許也加快了查詢。 –

回答

0

我推薦以下指標爲這個查詢:

ALTER TABLE Session_Fragen ADD INDEX sf_sess_fragen_id (
    Session_ID, 
    Userantwort1, 
    Userantwort2, 
    Userantwort3, 
    Userantwort4, 
    Userantwort5, 
    Sessionfrage_ID, 
    Frage_ID 
); 

我的理由是:

  • 首先加入等式謂詞引用的所有列。首先放置Session_ID列,因爲它很可能會縮短搜索範圍。

  • 在這些列之後,添加Sessionfrage_ID列進行排序。一旦搜索找到WHERE子句中條件的行,這些行就會有效地按順序排列。順序由索引的下一列確定,MySQL的優化器將使用此順序,而不必對匹配的行進行排序。

  • 最後,從選擇列表中添加Frage_ID列。這既不用於搜索也不用於排序,但將其包括在索引中會創建一個覆蓋索引的

我測試了這個,但沒有合理的測試數據,優化器沒有自動使用這個新的索引。如果我使用index hint來鼓勵它使用新的索引,我會得到一個更好的EXPLAIN報告(如果您在真實表上運行,索引提示可能是不必要的)。

mysql> explain SELECT Frage_ID FROM Session_Fragen use index (sf_sess_fragen_id) 
WHERE (Userantwort1 = 0 AND Userantwort2 = 0 AND Userantwort3 = 0 
    AND Userantwort4 = 0 AND Userantwort5 = 0) 
    AND Session_ID = 17898 
ORDER BY Sessionfrage_ID ASC LIMIT 1\G 
*************************** 1. row *************************** 
      id: 1 
    select_type: SIMPLE 
     table: Session_Fragen 
     type: ref 
possible_keys: sf_sess_fragen_id 
      key: sf_sess_fragen_id 
     key_len: 9 
      ref: const,const,const,const,const,const 
     rows: 1 
     Extra: Using where; Using index 

這個好東西解釋一下:

  • rows是很好的低,因爲Session_ID縮小搜索範圍。
  • Using index指示僅索引查詢(即覆蓋索引),這意味着查詢不必讀取表格行。
  • 我們沒有看到type: index(索引掃描),我們也不看Using filesort

有關設計索引的更多指導原則,請參閱我的演示文稿How to Design Indexes, Really

+0

THX了很多的支持。我會測試你推薦的所有失敗! – user2856074