Firebird 2.5 SQL 查询执行计划不使用带有 OR 语句的索引
Posted
技术标签:
【中文标题】Firebird 2.5 SQL 查询执行计划不使用带有 OR 语句的索引【英文标题】:Firebird 2.5 SQL query execution plan not using index with OR statement 【发布时间】:2016-11-29 15:43:47 【问题描述】:首先:我不是数据库专家,所以如果问题是微不足道的,请尽情享受......
我对子表CHILD
进行查询,在主表PARENT
中查找一些值以确定是否要加载条目。
查询如下所示
SELECT C.*, P.DATE, P.STATUS
FROM CHILD C, PARENT P
WHERE C.PARENT_ID = P.ID
AND (P.DATE > '01.01.2015' OR (P.STATUS <> 1 AND P.STATUS <> 9));
我特意选择了STATUS
值来强调我需要使用不等式,因为我需要从中选择的状态值是不连续的。
我在PARENT.ID
上有一个外键,用于字段CHILD.PARENT_ID
,并在CHILD.PARENT_ID
上创建了一个索引。我还在PARENT
字段DATE
和STATUS
上创建了一个索引。
现在,当我用 AND
和 AND
替换 OR
时,CHILD
使用 PARENT_ID
上的索引,PARENT
使用 DATE, STATUS
上的索引,这正是我所期望的。
但是当使用OR
时,查询使用CHILD
上的自然计划和PARENT.ID
上的主键索引。
如果我只将查询应用于父表,也会发生同样的情况:
SELECT P.* FROM PARENT P WHERE (P.DATE > '01.01.2015' OR (P.STATUS <> 1 AND P.STATUS <> 9));
有没有办法优化这样的查询以比自然计划更好地使用?
【问题讨论】:
能否请您在此处更新两个计划:Lhttps://www.brentozar.com/pastetheplan/..还有表数,两个表上的索引 请标记您正在使用的数据库。 请edit您的问题为有问题的表(包括所有索引)和执行计划添加create table
语句。 Formatted 文本 请no screen shots
【参考方案1】:
如果您写“或”,则每个 P.DATE 都可能是热门。每个 P.STATUS 也可能很受欢迎。如果您想使用索引,这不是很好的先决条件。
在这里,您必须帮助您的系统并提出 2 个单独的问题并将它们与 UNION 连接起来。喜欢
SELECT C.*, P.DATE, P.STATUS
FROM CHILD C, PARENT P
WHERE C.PARENT_ID = P.ID
AND P.DATE > '01.01.2015'
UNION
SELECT C.*, P.DATE, P.STATUS
FROM CHILD C, PARENT P
WHERE C.PARENT_ID = P.ID
AND P.STATUS <> 1
AND P.STATUS <> 9;
注意:如果 P.STATUS 的大多数值不等于 1 和不等于 9,那么您的性能仍然会很差。想象一下,您正在看一本书,所有单词都被索引,以查找单词“and”。它将出现在每一页;按顺序阅读会比使用索引更快。
【讨论】:
【参考方案2】:这对于优化器来说很难使用索引。首先,使用join
s 重写查询:
SELECT C.*, P.DATE, P.STATUS
FROM CHILD C JOIN
PARENT P
ON C.PARENT_ID = P.ID
WHERE P.DATE > '2015-01-01' OR P.STATUS NOT IN (1, 9);
你可以用UNION ALL
重写这个:
SELECT C.*, P.DATE, P.STATUS
FROM CHILD C JOIN
PARENT P
ON C.PARENT_ID = P.ID
WHERE P.DATE > '2015-01-01'
UNION ALL
SELECT C.*, P.DATE, P.STATUS
FROM CHILD C JOIN
PARENT P
ON C.PARENT_ID = P.ID
WHERE P.DATE <= '2015-01-01' AND -- This condition prevents overlaps
P.STATUS NOT IN (1, 9);
子查询现在可以使用PARENT(DATE, ID)
和PARENT(STATUS, DATE, ID)
上的索引。
但是,尚不清楚过滤结果实际上是否会使查询更快。这取决于过滤器的选择性。
【讨论】:
以上是关于Firebird 2.5 SQL 查询执行计划不使用带有 OR 语句的索引的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 C# Firebird 对数据库执行选择查询并将其显示在 shell 中?