我有这个SQL查询:
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;
在开始时,此查询运行速度非常慢。 我添加了索引来提高速度。 Bevor使用索引我扫描了大约。 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
显示指数:
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 :(得分: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
关于这个EXPLAIN的好消息:
rows
很好而且很低,因为Session_ID
缩小了搜索范围。Using index
表示仅索引查询(即覆盖索引),这意味着查询根本不必读取表行。type: index
(索引扫描),也看不到Using filesort
。有关设计索引的更多指南,请参阅我的演示文稿How to Design Indexes, Really。