我正在处理一些大型健康数据表(3B +行),并负责根据医疗代码列表标记和选择行。
考虑表EVENT
( id bigint
, edate date
, d1 char(5), d2 char(5), d3 char(5), d4 char(5), d5 char(5), d6 char(5), d7 char(5), d8 char(5), d9 char(5), d10 char(5)
, p1 char(5), p2 char(5), p3 char(5), p4 char(5), p5 char(5), p6 char(5), p7 char(5), p8 char(5), p9 char(5), p10 char(5)
, and many other fields
)
必须被查询并且标记为
select * from
(
select ...
, case when
p1 in (x1, ... ,xN1) or ... or p10 in (x1, ... ,xN1) then 'Y' else 'N' end as X_FLAG
, case when
p1 in (y1, ... yN2) or ... or p10 in (y1, ... ,yN2) then 'Y' else 'N' end as Y_FLAG
, case when
d1 in (z1, ... ,zN3) or ... or p10 in (z1, ... ,zN3) then 'Y' else 'N' end as Z_FLAG
, case when
d1 in (q1, ... ,qN4) or ... or d10 in (q1, ... ,qN4) then 'Y' else 'N' end as Q_FLAG
...
from EVENT
where
...
) tagged
into FURTHER_STUDY
where X_FLAG='Y' or Y_FLAG='Y' or Z_FLAG='Y' or Q_FLAG='Y'
随着搜索字段数和分配的标记数,查询持续时间会越来越长。
是否有更好的方法来制定速度查询? 例如,执行OR的快捷方式,或者每个长OR链是否更好作为更大的CASE语句?
可以/应该使用逐行扫描的程序吗?
答案 0 :(得分:0)
如果在运行时对30亿行进行任何类型的数据操作,特别是对于这么多case语句,查询将花费时间来处理数据。
毕竟3个billon行不是一个小数字。另外,我希望你在某种数据仓库中有这些3B行,而不是在OLTP数据库中。
我认为计算列可能是一种可能的解决方案。为Flag_X,Y Z G等添加这四列,并计算它们是否获得任何性能增益。
计算列的一个例子,类似于你的要求,就像......
DECLARE @t TABLE
( ID INT
, ID2 INT
, Flag_X AS (CASE WHEN ID IN (1,2) OR ID2 IN (1,2) THEN 1 ELSE 0 END) PERSISTED
, Flag_Y AS (CASE WHEN ID IN (2,3) OR ID2 IN (2,3) THEN 1 ELSE 0 END) PERSISTED)
INSERT INTO @t(ID , ID2) VALUES
(1 , 1),
(3 , 1),
(3 , 3)
SELECT * FROM @t
╔════╦═════╦════════╦════════╗
║ ID ║ ID2 ║ Flag_X ║ Flag_Y ║
╠════╬═════╬════════╬════════╣
║ 1 ║ 1 ║ 1 ║ 0 ║
║ 3 ║ 1 ║ 1 ║ 1 ║
║ 3 ║ 3 ║ 0 ║ 1 ║
╚════╩═════╩════════╩════════╝
答案 1 :(得分:0)
这是我可能会使用多个步骤的罕见案例之一,而不是试图将其纳入单一陈述。
但是如果我绝对不得不把它放到一个语句中,我会把这些标志放到他们自己的表中,然后我会加入该表而不是使用IN ()
子句。这将简化查询(无需列出可能很长的选择器列表)并提高性能(新标志表可以包含有助于Sql Server生成结果的索引和统计信息)。
我仍然不做的是写一个过程或光标来逐行扫描。如果需要,Sql Server已经可以做到这一点,并且正是这样做可能会导致为什么这会变慢。当我说“几个步骤”时,我的意思是更像是所有XFlags的一步,所有YFlags的一步等等。