【问题标题】:How can I make large IN clauses more efficient in SQL Server?如何在 SQL Server 中使大型 IN 子句更有效?
【发布时间】:2014-10-28 02:20:38
【问题描述】:

当访问具有相当大表的数据库时,我当前的查询运行速度非常慢

SELECT * 
FROM table1
WHERE timestamp BETWEEN 635433140000000000 AND 635433150000000000
  AND ID IN ('element1', 'element2', 'element3', ... , 'element 3002');

如您所见,IN 子句有数千个值。该查询大约每秒执行一次。

有没有其他的写法来提高性能?

【问题讨论】:

  • 有没有办法可以将元素链接到 Table1 中的字段。通过这样做,如果你把它们放在一个表中,你可以做一个简单的连接。这会稍微提高性能。
  • 查看查询的执行计划。如果查询速度很慢,则您缺少基础表上的索引和/或统计信息。如果元素来自另一个表,则加入该表而不是尝试创建 in 语句。
  • 元素从何而来?它们多久更换一次?
  • timestamp 列是否已编入索引?我假设 id 已经被索引了
  • 两个索引都存在。元素来自 c# 代码并经常更改。

标签: sql sql-server performance


【解决方案1】:

将 IN 的元素添加到索引临时表(如果元素更改)或永久表(如果元素是静态的)并在它们上进行内部连接。

【讨论】:

  • 打败我 ;)。我只是不确定静态表是否是 SO 的一个选项。
  • 如果timestampID 上没有适当的索引,这将无济于事。罪魁祸首很可能是未编入索引的 timestamp 列,而不是可能编入索引的 id
  • 在这种情况下不会太多。
【解决方案2】:

最佳答案取决于如何选择那些element ID 列表,但这一切都归结为一件事:将它们放入您可以加入的某个表中。这将极大地帮助性能。但同样,这里真正的问题是如何最好地将这些项目放入表格中,这将取决于问题中尚未包含的信息。

【讨论】:

    【解决方案3】:

    你应该检查你的执行计划,我猜你可能有一个参数嗅探问题是由你的 between.检查实际行是否与您的预期值相差甚远。您可以将您的 IN 重写为 EXISTS,它在内部就像 INNER JOIN 一样工作。

    【讨论】:

    • 查询优化器足够聪明,可以为 IN 或 EXISTS 创建相同的执行计划
    【解决方案4】:

    这是您的查询:

    SELECT *
    FROM table1
    WHERE timestamp BETWEEN 635433140000000000 AND 635433150000000000 AND
          ID IN ('element1', 'element2', 'element3', ... , 'element 3002');
    

    查询没问题。在table1(id, timestamp) 上添加索引。

    【讨论】:

      猜你喜欢
      • 2012-03-26
      • 1970-01-01
      • 2020-07-15
      • 2014-04-16
      • 2011-03-21
      • 1970-01-01
      • 1970-01-01
      • 2023-03-09
      • 1970-01-01
      相关资源
      最近更新 更多