具有极大IN子句的SQL Server查询会在活动监视器中导致大量查询

Kir*_*ace 3 sql t-sql sql-server

SQL Server 2014数据库.表有2亿行.

使用HUGE IN子句进行非常大的查询.

我最初为他们编写了这个查询,但他们已经将IN子句增加到700多个条目.CTE看起来没必要,因为为了简单起见,我省略了所有选择列及其substring()转换.

重点是IN子句.700多对这些.

WITH cte AS (
           SELECT *      
           FROM AODS-DB1B
           WHERE  
           Source+'-'+Target
    IN
    (
    'ACY-DTW',
    'ACY-ATL',
    'ACY-ORD',
    :
    : 700+ of these pairs
    :
    'HTS-PGD',
    'PIE-BMI',
    'PGD-HTS'
    )

    )

    SELECT *
    FROM cte
    order by Source, Target, YEAR, QUARTER
Run Code Online (Sandbox Code Playgroud)

在运行时,此查询会在几小时内将CPU发送到100% - 不出意外.

所涉及的所有列都有索引.

问题1:除了巨大的IN子句之外,是否有更好或更有效的方法来完成此查询?700 UNION ALL会更好吗?

问题2:当此查询运行时,它会创建一个包含49个"线程"的Session_ID(49个进程都具有相同的Session_ID).它们中的每一个都是此查询的一个实例,其中"Command"是此查询文本.

其中21个被暂停,其中14个正在运行,其中14个是RUNNABLE.

这在任务运行时会迅速变化.

到底发生了什么事?这个SQL Server是否会将查询分解成碎片来处理它?

Ale*_*lex 9

我建议您将700多个字符串存储在永久表中,因为通常认为在脚本中存储那么多元数据是不好的做法.您可以像这样创建表:

CREATE TABLE dbo.LookUp(Source varchar(250), Target varchar(250))

CREATE INDEX IX_Lookup_Source_Target on dbo.Lookup(Source,Target)

INSERT INTO dbo.Lookup (Source,Target)
SELECT 'ACY','DTW'
UNION
SELECT 'ACY','ATL'
.......
Run Code Online (Sandbox Code Playgroud)

然后你可以简单地加入这个表:

SELECT * FROM [AODS-DB1B] a
INNER JOIN dbo.Lookup lt ON lt.Source = a.Source 
                         AND lt.Target=a.Target
ORDER BY Source, Target, YEAR, QUARTER
Run Code Online (Sandbox Code Playgroud)

但是,更好的方法是规范化AODS-DB1B表和存储SourceId以及TargetIdINT值,而VARCHAR值存储在表SourceTarget表中.然后,您可以编写仅执行整数比较而不是字符串比较的查询,这应该快得多.