1

我有一个包含 700,000 个条目的数据库和一个快速文本搜索表。每行都有一个与之关联的时间。我需要一次有效地分页记录 100 行。我通过跟踪一天的结束来做到这一点。

执行时间太长(15 秒)

这是一个示例查询:

SELECT * 
FROM Objects o, FTSObjects f
WHERE f.rowid = o.AutoIncID AND 
  o.TimeStamp > '2012-07-11 14:24:16.582' AND 
  o.TimeStamp <= '2012-07-12 04:00:00.000' AND 
  o.Name='GPSHistory' 
ORDER BY o.TimeStamp 
LIMIT 100

时间戳字段已编入索引。

我认为这是因为该Order By语句正在对返回的所有记录进行排序,然后做了一个限制,但我不确定。

建议?

4

2 回答 2

2

是的,在ORDER BY之前处理LIMIT,但这是正确的功能。否则,分页实际上不会起作用。但是一些优化的想法。

  1. SELECT *如果不是绝对必要,不要这样做。我觉得这可能不是因为如果您对结果进行分页,几乎可以肯定不是用户正在查看的两个表中的每个字段。
  2. 创建一个覆盖索引AutoIncID, TimeStamp以防止它读取数据页。Name如果它来自 ,则添加到该索引Objects
  3. 如果来自rowid, Name,则在 上创建一个覆盖索引。NameFTSObjects
  4. 如果可以限制返回的字段,如果只有几个字段,请考虑将这些字段添加到涵盖的索引中。您不希望索引变得太大,因为那样会影响写入时间。
于 2013-07-11T20:17:00.883 回答
2

最好的方法是让优秀的 DBA 查看生成的计划并确保它是最佳计划(例如,确保计划中没有表扫描,如果优化器使用错误的统计信息,可能会发生这种情况)

以下是一些可能有帮助的事情:

  • 在和上添加一个索引Objects.Name- 甚至可能是一个复合索引。NameTimeStamp
  • 在其中添加一个索引rowidFTSObjects它尚不存在
  • UPDATE STATISTICS定期在Timestamp索引上(理想情况下在大更新之后或如果更新是连续的则每天)
  • 重建你的聚集索引(如果你有的话)。如果您的聚集索引位于没有顺序插入的字段上(例如,插入位于随机位置的 char 字段),这将有所帮助
  • select *如果不需要,不要这样做 - 这会增加 I/O时间

可以尝试将字符串转换为DATETIME,尽管我认为 SQL 隐式执行此操作,而不是将数据转换为字符串(不会使用日期时间的索引)

SELECT * 
FROM Objects o, FTSObjects f
WHERE f.rowid = o.AutoIncID AND 
  o.TimeStamp > CONVERT(DATETIME,'2012-07-11 14:24:16.582') AND 
  o.TimeStamp <= CONVERT(DATETIME,'2012-07-12 04:00:00.000') AND 
  o.Name='GPSHistory' 
ORDER BY o.TimeStamp 
LIMIT 100
于 2013-07-11T21:29:13.090 回答