【问题标题】:SQL query by time too slowSQL 按时间查询太慢
【发布时间】:2013-07-10 06:22:47
【问题描述】:

我有一个包含 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 语句正在对所有返回的记录进行排序,然后进行限制但我不确定。

建议?

【问题讨论】:

  • Timestamp 上的索引是我的建议。
  • 时间戳被索引@Matthew
  • 连接语法在这里JOIN FTSObjects f ON f.rowid = o.AutoIncID 也可能有所帮助,但我认为优化器已经为您做到了。
  • 我想知道在与 FTSObjects 隔离时提取 100 个对象行需要多长时间 - 即在该连接发生之前。 select o.autoincid from Objects o where o.timestamp....&lt;snip&gt; and o.name='GPSHistory' order by o.timestamp limit 100 当您在(timestamp,name) 上有一个复合索引并且timestamp 上的原始简单索引已被删除。
  • 另外,您的日期时间范围通常会获取多少条记录?您是在获取超过 100 条记录还是数千条记录?另外,反过来说,你能保证通过这种时间范围方法找到至少 100 条 GPSHistory 记录吗?

标签: c# sql database sqlite optimization


【解决方案1】:

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

以下几点可能会有所帮助:

  • Objects.Name 上添加索引 - 甚至可能在 NameTimeStamp 上添加复合索引。
  • FTSObjects 中的rowid 上添加一个索引,它尚不存在
  • 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

【讨论】:

  • 我认为我们的 SQLite 实现接受 DateTime 参数,但只是在内部使用字符串......对此不确定。您关于让 DBA 进行调查的建议让我考虑使用 EXPLAIN QUERY PLAN 命令。这让我看到正在使用错误的索引。 classname 列已编入索引,但只有 6 个唯一名称。我得到了使用时间戳作为索引的查询,现在速度快了大约 15 倍。
【解决方案2】:

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

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

【讨论】:

  • 解决方案与使用错误的索引有关。 classname 列只有六个唯一名称,并且被索引。我强制使用时间戳索引,现在页面在 1 秒内收集完毕。我尝试创建覆盖索引,但它们似乎并没有改善...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-31
  • 2021-06-19
  • 2022-01-27
  • 2010-12-15
相关资源
最近更新 更多