如何为2个SQL查询创建一个MySQL索引?

时间:2014-10-15 21:58:40

标签: mysql sql database indexing

SELECT * FROM messages_messages WHERE (from_user_id=? AND to_user_id=?) OR (from_user_id=? AND to_user_id=?) ORDER BY created_at DESC

我有另一个查询,即:

SELECT COUNT(*) FROM messages_messages WHERE from_user_id=? AND to_user_id=? AND read_at IS NULL

我想索引这两个查询,但我不想创建2个单独的索引。

现在,我使用了2个索引:

[from_user_id, to_user_id, created_at]
[from_user_id, to_user_id, read_at]

我想知道我是否可以用一个索引而不是两个索引来做到这一点? 这是我对此表的唯一2个查询。

2 个答案:

答案 0 :(得分:1)

The docs相当完整地解释了MySQL如何使用索引。特别是,它的优化器可以使用多列索引的任何左前缀。因此,您可以删除两个现有索引中的任何一个,而另一个则可以在两个查询中使用,尽管它对于一个查询比对另一个更有选择性/有用。

原则上,保留第一个索引可能更有利,前提是created_at列按降序编制索引。在实践中,MySQL允许您指定索引列顺序,但实际上只实现升序。因此,在索引中使用created_at可能并没有多大帮助。

答案 1 :(得分:0)

不,如果要完全优化,则需要这两个查询的两个索引。

一旦到达用于排序或范围比较的列(IS [NOT] NULL计为此目的的范围谓词),您就不会从索引中添加更多列中获得任何好处。换句话说,您的索引可以包含:

  1. 在等式谓词中使用的某些列
  2. 一个列,用于范围谓词,或避免使用filesort - 但不能同时使用两者。
  3. 额外的列既不用于搜索也不用于排序,但仅用于覆盖索引。
  4. 因此,您无法创建一个为两个查询提供服务的四列索引。

    正如@JohnBollinger所说,将这个减少到一个索引的唯一方法是创建一个优化一个查询的索引,并为第二个查询使用索引的子集。但那也行不通。