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是否会将查询分解成碎片来处理它?
我建议您将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值存储在表Source和Target表中.然后,您可以编写仅执行整数比较而不是字符串比较的查询,这应该快得多.