3

哪个复合索引会使这个简单的 MySQL 查询更快,我将如何创建该复合索引?

SELECT * 
FROM  `Table1` 
WHERE  `col1` =  '145307'
AND  `col2` =  '0'
AND col3 NOT 
IN ( 130209, 130839 ) 
ORDER BY col4 DESC 
LIMIT 0 , 5

col1上面的每一列 ( to 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
4

3 回答 3

6

我建议在 (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 计划中的“使用文件排序”。通常,如果您在不同的列上也有范围比较,则无法使用索引优化排序。

但是您至少可以使用三列索引来缩小搜索范围,这样文件排序就必须对一组较小的行进行处理,然后它可能会在内存中完成。

另请参阅我的演示文稿如何设计索引,真的

于 2012-12-12T20:36:49.620 回答
0

如果您要创建复合索引,那么在作为复合索引成员的各个列上创建索引将是多余的。找出您最常运行的查询、查询中涉及的每列的基数、查询将返回的大致行数、表中的总行数、表是否经常更新等。记住索引插入和更新的成本。

于 2012-12-14T06:17:11.007 回答
0

目前最好的答案是最可怕的。每次在 EXPLAIN 中看到“文件排序”时,它都会非常慢,因为 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 再次与表连接(在另一个快速索引操作中)以获得完整的详细信息。

于 2013-04-09T16:17:58.170 回答