首先:我不是数据库专家,所以如果这个问题很简单,请放纵......
我在子表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
的{{1}}上有一个外键,并在CHILD.PARENT_ID
上创建了一个索引。我还在字段CHILD.PARENT_ID
和PARENT
上的表DATE
上创建了一个索引。
现在,当我将STATUS
替换为OR
AND
使用CHILD
上的索引而PARENT_ID
使用PARENT
上的索引时这是我所期待的。
但在使用DATE, STATUS
时,查询会使用OR
上的自然计划和CHILD
上的主键索引。
如果我仅将查询应用于父表,则会出现相同的情况:
PARENT.ID
有没有办法优化这样的查询以比自然计划更好地使用?
答案 0 :(得分:2)
如果你写的是&#39;或&#39;,每个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,那么你的性能仍然不佳。想象一下,你会在一本书中找到所有单词索引的单词&#39;和&#39;。它将在每一页;按顺序阅读本书比使用索引更快。
答案 1 :(得分: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)
上的索引。
但是,过滤结果实际上会使查询更快,这一点尚不清楚。这取决于过滤器的选择性。