Sql server 参数值过多会减慢查询速度

Sql server 参数值过多会减慢查询速度,sql-server,tsql,optimization,ssms,Sql Server,Tsql,Optimization,Ssms,我有一个查询在正常情况下运行得相当快。但是由于过滤器中有多少值,它运行得非常慢(在SSMS中至少20分钟) 这是它的通用版本,您可以看到一个部分通过8000多个值进行过滤,使其运行缓慢 SELECT DISTINCT column FROM table_a a JOIN table_b b ON (a.KEY = b.KEY) WHERE a.date BETWEEN @Start and @End AND b.ID IN (... over

我有一个查询在正常情况下运行得相当快。但是由于过滤器中有多少值,它运行得非常慢(在SSMS中至少20分钟)

这是它的通用版本,您可以看到一个部分通过8000多个值进行过滤,使其运行缓慢

SELECT DISTINCT 
    column 
FROM 
    table_a a 
JOIN 
    table_b b ON (a.KEY = b.KEY)
WHERE 
    a.date BETWEEN @Start and @End
    AND b.ID IN (... over 8,000 values)
    AND b.place IN ( ... 20 values)
ORDER BY 
    a.column ASC
它的速度太慢,无法在生产应用程序中使用


有人知道如何解决这个问题或优化查询吗?

您需要的是将筛选值放入临时表中。然后使用该表使用
内部联接
而不是
中的WHERE应用筛选。例如:

IF OBJECT_ID('tempdb..#FilterDataSource') IS NOT NULL
BEGIN;
    DROP TABLE #FilterDataSource;
END;

CREATE TABLE #FilterDataSource
(
    [ID] INT PRIMARY KEY
);

INSERT INTO #FilterDataSource ([ID])
-- you need to split values

SELECT DISTINCT column 
FROM table_a a 
INNER JOIN table_b b 
    ON (a.KEY = b.KEY)
INNER JOIN #FilterDataSource FS
    ON b.id = FS.ID
WHERE a.date BETWEEN @Start and @End
    AND b.place IN ( ... 20 values)
ORDER BY .column ASC;
几点重要提示:

  • 我们使用临时表是为了允许使用并行执行计划
  • 如果您有fast(例如CLR函数)用于spiting,则可以加入函数本身
中使用许多值是不好的,SQL Server无法始终构建执行计划,这可能会导致超时/内部错误-您可以找到更多信息
您需要的是将筛选值放入临时表中。然后使用该表使用
内部联接
而不是
中的WHERE应用筛选。例如:

IF OBJECT_ID('tempdb..#FilterDataSource') IS NOT NULL
BEGIN;
    DROP TABLE #FilterDataSource;
END;

CREATE TABLE #FilterDataSource
(
    [ID] INT PRIMARY KEY
);

INSERT INTO #FilterDataSource ([ID])
-- you need to split values

SELECT DISTINCT column 
FROM table_a a 
INNER JOIN table_b b 
    ON (a.KEY = b.KEY)
INNER JOIN #FilterDataSource FS
    ON b.id = FS.ID
WHERE a.date BETWEEN @Start and @End
    AND b.place IN ( ... 20 values)
ORDER BY .column ASC;
几点重要提示:

  • 我们使用临时表是为了允许使用并行执行计划
  • 如果您有fast(例如CLR函数)用于spiting,则可以加入函数本身
中使用许多值是不好的,SQL Server无法始终构建执行计划,这可能会导致超时/内部错误-您可以找到更多信息
要快速查询,需要索引。 以下列需要单独的索引:a.KEY、b.KEY、a.date、b.ID、b.place。
正如gotqn之前所写的,如果将8000个项目放入临时表,并对其进行内部联接,则查询速度也会更快,但如果联接的另一部分没有索引,则查询速度也会变慢。

要快速进行查询,需要索引。 以下列需要单独的索引:a.KEY、b.KEY、a.date、b.ID、b.place。
正如gotqn之前所写的,如果将8000个项目放入临时表,并对其进行内部联接,则查询速度也会更快,但如果联接的另一部分没有索引,则查询速度也会变慢。

使用适当的软件(MySQL、Oracle、DB2等)和版本标记数据库问题是很有帮助的,例如
sql-server-2014
。语法和特征的差异通常会影响答案。并提供模式。和索引。以及实际执行计划。尝试使用在vs内部联接中搜索
t sql
。你会发现类似的文章可能会有所帮助。你为什么感到困惑?您正在每行执行8K+逻辑检查,当然速度会很慢。您应该问的真正问题是如何编写一个更优化的查询,而不是为什么次优化的查询显然很慢。你能解释一下为什么你可能有一个带8k选项的IN吗?这8000个值是从哪里来的,为什么它们不在数据库本身的一个表中?基本上,您是针对第三个具有8K行的表进行连接。
表b.ID
是否包含在索引中?它被使用了吗?如果不是,则强制搜索8000个值。执行计划是什么?在
a.Date
b.ID
b.place
列上有索引吗?如果不这样做,则强制执行L x M x N搜索,这显然会随着传递的项目越多而变慢。使用适当的软件(MySQL、Oracle、DB2等)和版本(例如,
sql-server-2014
)标记数据库问题很有帮助。语法和特征的差异通常会影响答案。并提供模式。和索引。以及实际执行计划。尝试使用在vs内部联接中搜索
t sql
。你会发现类似的文章可能会有所帮助。你为什么感到困惑?您正在每行执行8K+逻辑检查,当然速度会很慢。您应该问的真正问题是如何编写一个更优化的查询,而不是为什么次优化的查询显然很慢。你能解释一下为什么你可能有一个带8k选项的IN吗?这8000个值是从哪里来的,为什么它们不在数据库本身的一个表中?基本上,您是针对第三个具有8K行的表进行连接。
表b.ID
是否包含在索引中?它被使用了吗?如果不是,则强制搜索8000个值。执行计划是什么?在
a.Date
b.ID
b.place
列上有索引吗?如果你不这样做,你会强制执行一个L x M x N搜索,这显然会变得越慢,你通过的项目越多,这将大大降低速度。临时表不影响并行执行。真正的问题是临时表没有主键或索引,导致对每个ID进行完整的表扫描。(…)操作中的
至少知道值的统计信息。这个临时表只是一个无序的堆。临时表比TVP更受欢迎,因为它们有统计信息,而TVP没有——它们被视为一行表。
IN()
操作符也有统计信息,这就是为什么它比TVP更快的原因。我就是这么说的。这是关于TVP与临时表的比较。OP没有使用TVPs。您没有使用索引,因此没有统计信息。您的解决方案会更糟糕,因为它没有索引,没有统计信息,并且会命中磁盘。至少TVP可能不会。如果要获得任何性能增益,请添加主键。毫无疑问,如果表很宽并且有列值存储在行外,则使用正确的索引是最好的。也没有关于表结构的信息,因此交谈是无用的。我添加了这一点,因为一周前我调试的一个动态查询在
子句中使用了数千个值进行过滤-如果是OP的情况,这将