0

我有一张类似这样的表格(为了便于解释,我删除了很多字段)。orderId 是一个 int 非唯一值,用于显示一行的重要性(我在返回数据时按它排序)

CREATE TABLE `my_images` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `orderId` int(11) NOT NULL,
  `slug` varchar(50) NOT NULL,
  `imageFilename` varchar(255) NOT NULL,
  `thumb200` varchar(255) NOT NULL,
  `thumb600` varchar(255) NOT NULL,
  `md5hash` varchar(255) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `orderId` (`orderId`),
  KEY `thumb600` (`thumb600`),
  KEY `slug` (`slug`),
  KEY `multiple_1` (`md5hash`,`orderId`,`thumb200`,`thumb600`),
  KEY `md5hash` (`md5hash`),
  KEY `thumb200` (`thumb200`),
  KEY `thumb200_2` (`thumb200`,`orderId`),
  KEY `orderId_2` (`orderId`,`thumb600`,`thumb200`),
  KEY `thumb600_2` (`thumb600`,`orderId`),
  KEY `thumb600_3` (`thumb600`,`orderId`),
  KEY `orderId_3` (`orderId`,`thumb600`),
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

是的 - 有很多索引涵盖 orderId。它混合了尝试解决当前问题的方法,并且因为我在 WHERE 语句中使用了这些字段。

无论如何,如果我运行此命令:

explain SELECT id FROM my_images
 ORDER BY orderId asc

它输出这个(“使用索引”)

id  select_type table   type    possible_keys   key key_len ref rows    Extra
1   SIMPLE  my_images   index   NULL    orderId 4   NULL    174553  Using index

这是预期的 - orderId 是一个索引。

但如果我这样做:

explain SELECT id,   thumb600, imageFilename,  slug FROM my_images
 ORDER BY orderId asc

它输出这个(使用文件排序):

id  select_type table   type    possible_keys   key key_len ref rows    Extra
1   SIMPLE  my_images   ALL NULL    NULL    NULL    NULL    174553  Using filesort

奇怪的是,如果我这样做

explain SELECT id,  md5hash  FROM my_images
 ORDER BY orderId asc

它说“使用索引;使用文件排序”

id  select_type table   type    possible_keys   key key_len ref rows    Extra
1   SIMPLE  my_images   index   NULL    multiple_1  775 NULL    174553  Using index; Using filesort

我注意到的原因是因为我看到了一个缓慢的查询,它基本上是“选择(一堆字段) order by orderId limit 4000,3 ”,这需要很长时间,在运行解释命令后看到了。有什么办法让它总是使用索引?我是否必须创建一个包含我选择的所有字段的索引?如果是这样,索引中字段的顺序是否重要?

4

2 回答 2

3

如果您选择索引未涵盖的列,引擎将不得不进行表查找以获取这些列的值。

由于您无论如何都在选择整个表(不使用WHEREor LIMIT),因此顺序扫描表然后对其进行排序会更快,而不是进行大量的键搜索。

此外,MySQL不能进行后期行查找,这意味着它总是在计算偏移量之前查找表,即使使用索引也是如此。

如果您按表中的非 PK 字段排序InnoDB,请尝试以下操作:

SELECT  i.*
FROM    (
        SELECT  id
        FROM    my_images
        ORDER BY
                orderId
        LIMIT   4000, 3
        ) q
JOIN    my_images i
ON      i.id = q.id

请参阅我的博客中的这篇文章以获得解释:

于 2013-04-24T21:23:52.397 回答
2

添加索引顺序 ID,然后添加您想要作为索引的列

问题是当您添加其他列时,文件排序就像便笺一样,它必须重新收集它们

但是,如果您在索引中有列(它必须是一个具有 4-6 列的索引),因为每个查询将只使用一个索引。列将一起去兜风

于 2013-04-24T21:49:15.143 回答