2012-06-10 46 views
2

我有一个SQL查询,它获取设计为低级队列的表中的前N行。优化查询与列在哪里条款

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

此查询背后的意图是如下:

  • 首先,这个问题的目的是数据库无关,因为我实现将支持SQL服务器,Oracle,DB2和Sybase。上面的“top N”的sql语法只是一个例子。
  • 该表可以包含数百万行。
  • N是一个比较小的数字,例如, 100.
  • 行在队列中时,状态为0。稍后它会更改为1以指示它正在处理中。处理后它被删除。因此,预计表格中至少90%的行将具有状态0.
  • 表中的行应根据其日期取得,因此应该取order by子句。

什么是使此查询最快的最佳索引?

我最初认为该指数应该在(date, status),但我不知道它了。由于状态列将大部分为零,是否有附加值?单独索引(date)是否足够?
或者它应该是(status, date)

回答

2

我不认为有一个有效的解决方案将独立于RDMS。例如,Oracle具有位图索引,SQLServer具有部分索引,并且如果例如Mysql或Sqlite没有任何相似性,我不会看到不使用它们的理由。此外,历史上SQLServer实现聚集表(或甲骨文世界中的IOT)比Oracle更好,因此日期列上的聚集索引对于SQLServer可能完美工作,但对Oracle不起作用。

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

+0

90%的行将*的状态= 0。我不想重构模式,整个问题是从表中获取记录,更改status = 1,然后进行一些处理。处理完成后,这些记录将被删除。为了确保高可用性,我会定期扫描表,查找状态为1的记录,这些记录没有经过处理(例如,服务器在读取后出现故障) – Yoni

+0

您可以尝试按状态字段对分区表进行分区。所以你将有逻辑上1个表格存储在2个分区。据我所知,大多数RDMS支持分区... – a1ex07

0

在日期上有聚簇索引,在状态上有非聚簇索引。

+1

在Date上有一个聚集索引对SQL服务器有意义,但在Oracle中创建表IOT之前,我认为[至少]两次。除了可能的性能开销,如果日期列不是唯一的,它还需要额外的列。与状态索引恰恰相反 - Oracle位图索引非常适合此目的,SQLServer(B-tree)索引不是。 – a1ex07

+0

你能否详细解释原因? – Yoni

+0

正如@ a1ex07所评论的那样,我建议牢记SQL Server,我认为这是对的。有关更多信息,您可以搜索sql server中聚集索引和非聚集索引之间的区别。 – Luftwaffe