在 where 和 orderby 子句中使用两个单列索引

rez*_*eza 0 mysql sql indexing query-optimization where-clause

我用谷歌搜索了很多,但找不到我的问题的明确答案

假设我们有这个查询

SELECT * WHERE user_id = x ORDER BY date_created
Run Code Online (Sandbox Code Playgroud)

如果我们在 user_id 上有一个单列索引,在 date_created 上有另一个单列索引,优化器是否会使用这两个索引?或者只是 user_id 索引?

GMB*_*GMB 5

这是您的查询:

SELECT *
FROM mytable
WHERE user_id = 123 
ORDER BY date_created
Run Code Online (Sandbox Code Playgroud)

如果您有两个不同的索引,那么 MySQL 可能会使用索引 onuser_id来应用where谓词(如果它认为这会加快查询速度,具体取决于数据的基数和其他因素)。它不会使用 上的索引date_created,因为它无法将满足谓词的中间结果集where与该索引相关联。

对于此查询,您需要上的复合索引(user_id, date_created)。数据库使用索引中的第一个键来过滤数据集:在索引 B 树中,匹配的行已经按日期排序,因此该order by操作变为无操作。

我注意到你正在使用select *; 一般来说,这不是一个好的做法,也不利于性能。如果表中除了用户和日期之外还有其他列,这会迫使数据库在通过索引过滤和排序后查找表以获取相应的行,这可能比根本不使用索引的成本更高。如果您只需要几列,则枚举它们:

SELECT date_created, first_name, last_name 
FROM mytable
WHERE user_id = 123 
ORDER BY date_created
Run Code Online (Sandbox Code Playgroud)

并有一个索引(user_id, date_created, first_name, last_name)。这是一个覆盖索引:数据库可以使用索引执行整个查询,而无需查找表本身。

  • 。。当过滤查询时,文档的这一部分可能不相关。它试图避免一种称为“颠簸”的情况,即表不适合内存并且被乱序读取。文档在这一点上应该很清楚。而且,它实际上并不是关于“select *”,而是关于除索引中的键之外的“任何”列。天哪,文档的那部分确实具有误导性。 (2认同)