【问题标题】:optimize query with column in where clause使用 where 子句中的列优化查询
【发布时间】:2012-06-10 14:27:33
【问题描述】:

我有一个 sql 查询,它获取表中的前 N ​​行,该表被设计为低级队列。

select top N * from my_table where status = 0 order by date asc

这个查询的意图如下:

  • 首先,这个问题与数据库无关,因为我的实现将支持 sql server、oracle、DB2 和 sybase。上面“top N”的sql语法只是一个例子。
  • 该表可以包含数百万行。
  • 相比之下,N 是一个相对较小的数字,例如100.
  • 当行在队列中时状态为 0。稍后它变为 1 表示它正在处理中。处理后删除。因此,预计表中至少 90% 的行的状态为 0。
  • 应根据日期获取表中的行,因此应使用order by 子句。

使这个查询运行得最快的最佳索引是什么?

我最初认为索引应该在(date, status) 上,但我现在不确定了。由于状态列将大部分包含零,它是否有附加值?仅按(date) 索引就足够了吗?
或者应该是(status, date)

【问题讨论】:

    标签: sql database database-agnostic


    【解决方案1】:

    我认为没有独立于 RDMS 的有效解决方案。例如,Oracle 有位图索引,SQLServer 有部分索引,如果 Mysql 或 Sqlite 没有类似的东西,我看不出不使用它们的理由。此外,从历史上看,SQLServer 实现聚集表(或 Oracle 世界中的 IOT)的方式比 Oracle 更好,因此在日期列上具有聚集索引可能对 SQLServer 非常有效,但不适用于 Oracle。

    我宁愿稍微改变一下方法。如果您说 90% 的行不满足status=0 条件,为什么不尝试重构模式,并添加一个仅包含您感兴趣的记录的新表(或物化视图)?即使 RDMS 不直接支持物化视图,保持该表最新并将数据与原始表合并所需的新可编程对象的数量也相对较少。另外,如果可以重新设计底层逻辑,使行永远不更新,只插入或删除,那么这将有助于避免锁争用,从而使整个系统具有更好的性能。

    【讨论】:

    • 90% 的行的状态=0。我不想重构schema,重点是从表中获取记录,更改status=1,然后做一些处理。处理后,这些记录将被删除。为确保 HA,我会定期扫描表中未处理的 status=1 记录(例如,服务器在获取它们后停机)
    • 您可以尝试按状态字段对表进行分区。因此,您将在逻辑上拥有 1 个存储在 2 个分区中的表。据我所知,大多数 RDMS 都支持分区...
    【解决方案2】:

    在 Date 上有一个聚集索引,在 Status 上有一个非聚集索引。

    【讨论】:

    • 在 Date 上有一个聚集索引对 SQL 服务器来说是有意义的,但在 Oracle 中创建表 IOT 之前,我会考虑 [至少] 两次。如果日期列不是唯一的,除了可能的性能开销之外,它还需要额外的列。与 Status 上的索引完全相反 - Oracle 位图索引非常适合此目的,而 SQLServer(b-tree)索引则不是。
    • 你能详细解释一下原因吗?
    • 正如@a1ex07 评论的那样,我建议牢记SQL Server,我认为这是正确的。更多信息可以搜索sql server中聚集索引和非聚集索引的区别。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-17
    • 2022-10-24
    相关资源
    最近更新 更多