【问题标题】:SQL index design regarding joins, filters, and ORDER BY关于连接、过滤器和 ORDER BY 的 SQL 索引设计
【发布时间】:2013-04-13 05:45:21
【问题描述】:

我正在优化 DB2 LUW 数据库的一些查询,并且我将重组一些现有的索引。但是,我有一些关于似乎没有明确定义的主题的问题,至少从我能够找到的内容来看。对于初学者,以下是查询本身的概要:

SELECT 
--About a dozen fields from TABLE A--
--A few fields from joined tables--
FROM
TABLE A
--A few inner join/left joins, mostly on A.ID1 and A.ID2, BIGINT generated keys--
WHERE
A.ONE = :x
AND A.TWO IN (:y)
AND A.THREE IN (--uncorrelated suquery--)
AND A.FOUR IS NULL
AND (A.FIVE BETWEEN :date1 AND :date2
OR
A.SIX = 'STUFF')
ORDER BY A.SEVEN

注意几点:

  • 仅 A.ID1 和 A.ID2 上有一个索引,可能是聚集索引,因为这是主键
  • A.SEVEN 上有一个索引
  • 我正在修改 WHERE 子句中其余字段的索引

所以所有的连接/过滤/排序列都被索引了。问题是:它们应该全部组合成一个索引还是分开?如果我将 A.SEVEN 放入同一个索引中,我是否仍想根据选择性放置它,还是因为没有过滤,只有排序,所以这无关紧要?

编辑: 我发现自己使用了一种通常更快的 OR 子句替代方案,至少在我正在使用的查询中:

CASE WHEN (first statement) THEN 1 
WHEN (second statement) THEN 1 
ELSE 0 
END = 1

这在某些查询上出奇地有效,但与 OR 子句相比,我不确定它是否/如何影响索引的使用。此外,从 ONE 到 FOUR 是否最好按照选择性顺序进行组织,即,如果 FOUR 只有 12 个不同的值,而 ONE 有 10k,那么最好将 ONE 放在索引的前面。

【问题讨论】:

    标签: sql join indexing db2 sql-order-by


    【解决方案1】:

    我对 DB2 对索引的特定处理并不十分熟悉。但是假设它和其他数据库一样,我认为您将无法使用索引进行最终排序。

    基于where 子句的此查询的良好索引是A(one, two, three, four)。之后,由于or 条件,您被困在five 和six 之间。您可以将其中任何一个放入索引中。将两者都放入可能不会有什么不同——只有第一个会被使用,第二个会通过扫描索引的那个部分来找到满足另一个条件的行来解决。

    换句话说,索引的实用性在你到达seven之前就已经结束了。

    如果 DB2 真的很复杂,它可能能够利用两个索引,A(one, two, three, four, five) 和 A(one, two, three, four, six)。再一次,由于or 条件,索引对order by 没有帮助。

    由于相等条件,one、two、three 和 four 在索引中按任意顺序排列。有一个警告。我不知道 db2 如何使用子查询处理 in 条件。我倾向于在A(one, two, four, three) 上建立索引。

    【讨论】:

    • 我已经能够删除 OR 语句。见上文。
    • @user1017413 。 . . case 语句在语义上是不同的,因为子句强加了一个顺序。这意味着您将以与case 语句中相同的顺序将变量插入索引中,假设 DB2 足够聪明,可以识别这一点。
    • 不错。这是朝着正确方向迈出的一步。现在我需要确定将它们放在索引中的位置和方式。我在测试环境中的 CREATE/DROP 王国......不过,我们都学到了一件事:OR 子句是邪恶的。
    猜你喜欢
    • 2013-04-13
    • 1970-01-01
    • 1970-01-01
    • 2022-01-17
    • 1970-01-01
    • 1970-01-01
    • 2021-12-28
    • 1970-01-01
    相关资源
    最近更新 更多