哪个复合索引会使这个简单的MySQL查询更快,如何我会创建该复合索引?
SELECT *
FROM `Table1`
WHERE `col1` = '145307'
AND `col2` = '0'
AND col3 NOT
IN ( 130209, 130839 )
ORDER BY col4 DESC
LIMIT 0 , 5
上面的每一列(col1
到col4
)都有一个单独的索引。
修改:
SHOW CREATE TABLE
的结果:
CREATE TABLE `Table1` (
`primaryCol` int(11) NOT NULL AUTO_INCREMENT,
`col3` int(11) DEFAULT '0',
`col5` varchar(20) COLLATE utf8_bin DEFAULT NULL,
`col1` int(11) DEFAULT '0',
`col6` varchar(80) COLLATE utf8_bin DEFAULT NULL,
`col7` text CHARACTER SET utf8,
`col4` int(11) DEFAULT '0',
`col8` char(1) COLLATE utf8_bin DEFAULT 'N',
`col9` char(1) COLLATE utf8_bin DEFAULT 'N',
`col2` tinyint(1) NOT NULL,
`col10` tinyint(1) NOT NULL,
`col11` smallint(6) NOT NULL,
PRIMARY KEY (`primaryCol`),
KEY `col5` (`col5`),
KEY `col1` (`col1`),
KEY `col3` (`col3`),
KEY `col4` (`col4`),
KEY `col8` (`col8`),
KEY `col9` (`col9`),
KEY `CompIndex1` (`col1`,`col8`,`col4`),
KEY `col2` (`col2`),
KEY `col10` (`col10`),
KEY `col11` (`col11`),
FULLTEXT KEY `col7` (`col7`)
) ENGINE=MyISAM AUTO_INCREMENT=4575350 DEFAULT CHARSET=utf8 COLLATE=utf8_bin
EXPLAIN EXTENDED
的结果:
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE Table1 ref col1,col3,CompIndex1,col2 CompIndex1 5 const 226 100 Using where; Using filesort
答案 0 :(得分:5)
我建议使用索引(col1,col2,col3)。
mysql> CREATE INDEX NewIndex ON Table1 (col1,col2,col3);
mysql> EXPLAIN SELECT * FROM `Table1` WHERE `col1` = '145307'
AND `col2` = '0' AND col3 NOT IN ( 130209, 130839 )
ORDER BY col4 DESC LIMIT 0 , 5\G
id: 1
select_type: SIMPLE
table: Table1
type: ref
possible_keys: col1,col3,CompIndex1,col2,NewIndex
key: NewIndex
key_len: 6
ref: const,const
rows: 1
Extra: Using where; Using filesort
你对col3的条件不是相等比较,它是一个范围比较,它应该是索引中的最后一列。
不幸的是,这意味着您无法摆脱EXPLAIN计划中的“使用filesort”。通常,如果您还在不同列上进行范围比较,则无法使用索引优化排序。
但是你至少可以使用三列索引来缩小搜索范围,这样filesort就必须在一组较小的行上工作,然后它可能会在内存中完成。
答案 1 :(得分:0)
如果要创建复合索引,那么在作为复合索引成员的各列上建立索引将是多余的。确定您最常运行的查询,查询中涉及的每列的基数,查询返回的大致行数,表中的总行数,是经常更新的表等。请记住索引插入和更新的成本。
答案 2 :(得分:0)
目前最好的答案是最可怕的答案。每次在EXPLAIN中看到“filesort”时,它都会非常慢,因为MySQL必须创建临时文件并且不使用索引进行排序!
索引就像电话簿。在您的情况下,正确的索引将是:
(col4,col1,col2,col3,primaryCol)
订单很重要!复合索引的最左侧部分必须始终是您要排序的列。然后,添加在WHERE子句中使用的其他列。最后,对于MyISAM,您还需要添加主键(InnoDB会自动添加)。
此外,您需要更改您的查询,以便分离/过滤和获取完整的详细信息:
SELECT * FROM `Table1` JOIN (
SELECT primaryKey FROM `Table1`
WHERE `col1` = '145307'
AND `col2` = '0'
AND col3 NOT
IN ( 130209, 130839 )
ORDER BY col4 DESC
LIMIT 0 , 5
) foo ON Table1.primaryKey=foo.primaryKey
使用EXPLAIN进行检查,您将看到正确的索引用法,用于排序和过滤。然后,结果ID再次与表(在另一个快速索引操作中)连接,以获取完整的详细信息。