在我的许多查询中,我都有像
这样的场景SELECT * from myTable m
where m.userId = :userId
AND (m.to = :contactNumber OR m.from = :contactNumber)
AND .....
所以我为(userId,to,from)
创建了一个复合索引如果OR
替换为AND
,则效果正常,但OR
只使用userId
的索引。
我有点困惑,为什么会发生这种情况,还有什么更好的方法来对此进行索引以提高性能,可能会单独索引所有这些吗?
答案 0 :(得分:2)
复合索引搜索混合在一起的几个东西。将它看作是连接的各列的索引可能会有所帮助。
因此,如果您使用或,您正在寻找userid和to,OR userid和from的组合。但不是所有3个在一起!
它有点取决于内容和所有内容,但您可以为两个“子”查询添加2个复合(所以userid和+ userid和from)。但是用户ID索引不够吗?如果这样会占用足够的行以使其可以管理,我就不会去添加各种复合索引......
答案 1 :(得分:2)
您只需要考虑如何将复合索引放在一起。密钥主要按userId
排序。在每个userId
中,它们将按to
排序,并且在每个这些组中,它将按from
排序。
这意味着,虽然您可以使用该索引查找特定的userId
值,userId:to
对和userId:to:from
三元组,但找到特定的userId:from
对并不是很好。这是因为这些值将在索引顺序中的许多不同位置,因为to
是比from
更高级别的键。
执行此操作的一种方法是在userId:from
上添加一个额外的索引,然后在联合中使用两个单独的查询,这两个查询都可以使用自己的索引来有效地查找行。类似的东西:
select * from myTable m
where m.userId = :userId and m.to = :contactNumber
union
select * from myTable m
where m.userId = :userId and m.from = :contactNumber
第一个查询很可能会使用原始索引,因为userId:to
是它的两个顶级组件。您可能也有一个索引,但它可能没有必要,因为您已经有一个可用的索引(并且可能用于您想要所有三个组件的行的其他查询)。
第二个查询可能会使用新索引来有效地查找其行。
union
将他们合并两个查询并删除重复项。这需要匹配原始查询的意图。如果您知道查询之间可能没有交叉,那么您可以使用union all
跳过(不必要的)重复删除步骤,但我认为您不能在此处执行此操作。
此方法还具有在支持它的数据库中容易受到并行性的潜在优势(查询可以并行运行,并且一旦完成,就可以组合)。
现在请记住这是一般建议。我自己就是一个DB2人,所以我在这里提出的是基于数据库内部工作的一般知识,而不是MySQL的具体细节。
您仍然应该测试查询以确保它们按预期运行(但我认为即使我是MySQL的 author ,您也希望这样做)。换句话说,我已经失去了数次我在这里说了多少次,测量,不要猜测!