在SQL Server

时间:2017-08-18 23:21:49

标签: sql-server query-performance generated-code

我正在处理的应用程序生成一个SQL查询,如下所示:

Select 
    VISIT_VIEW.VISIT_ID, VISIT_VIEW.PATIENT_ID, VISIT_VIEW.MRN_ID, 
    VISIT_VIEW.BILL_NO, INSURANCE.INS_PAYOR'
FROM 
    'VISIT_VIEW 
LEFT JOIN 
    INSURANCE ON VISIT_VIEW.visit_id = INSURANCE._fk_visit '
WHERE 
    'VISIT_VIEW.VISIT_ID IN (1002, 1003, 1005, 1006, 1007, 1008, 1010, 1011, <...>, 1193, 1194, 1195, 1196, 1197, 1198, 1199)'

<...>表示一长串ID。列表的大小取决于先前查询的结果,进而取决于选择用于生成该查询的参数。

ID列表可以是从100项到2000以上的任何地方。

INSURANCE表很大,超过900万行。访问表也很大,但不是很大。

随着身份证数量的增加,从不到一秒的持续时间到超过15分钟的数量会有相当大的增长。增长开始大约175 ids。

如果更改了用于生成查询的参数,以便未选择INS_PAYOR列,因此没有左连接,则查询在不到一秒的时间内运行,即使在超过2000个项目中也是如此ID列表。

执行计划显示97%的查询时间用于INSURANCE表上的集群搜索。

如何以较少可怕的延迟重新设计此查询以获得相同的结果?

请记住,SQL是由代码生成的,而不是手工生成的。它是从字段列表(知道哪个字段属于哪个表)和要检查的主表中的ID列表生成的。我可以访问执行查询生成的代码,并且可以更改它,前提是查询的最终结果完全相同。

谢谢

2 个答案:

答案 0 :(得分:0)

  

&lt; ...&gt;代表一长串的ID。列表的大小取决于先前查询的结果

不要那样做

这样做:

SELECT <...>
FROM VISIT_VIEW 
INNER JOIN (
    <previous query goes here>
) t on VISIT_VIEW.VISIT_ID = t.<ID?>
LEFT JOIN INSURANCE ON VISIT_VIEW.visit_id=INSURANCE._fk_visit

答案 1 :(得分:0)

使用以下内容查看是否有任何改进...

IF OBJECT_ID('tempdb..#VisitList', 'U') IS NOT NULL 
DROP TABLE #VisitList;

CREATE TABLE #VisitList (
    VISIT_ID INT NOT NULL PRIMARY KEY
    );

INSERT #VisitList (VISIT_ID) VALUES (1002),(1003),(1005),(1006),(1007),(1008),(1010),(1011),(<...>),(1193),(1194),(1195),(1196),(1197),(1198),(1199);

SELECT 
    vv.VISIT_ID, 
    vv.PATIENT_ID, 
    vv.MRN_ID, 
    vv.BILL_NO, 
    ix.INS_PAYOR
FROM 
    VISIT_VIEW vv
    JOIN #VisitList vl
        ON vv.VISIT_ID = vl.VISIT_ID
    CROSS APPLY (
                SELECT TOP 1
                     i.INS_PAYOR
                FROM 
                    INSURANCE i
                WHERE 
                    vv.visit_id=i._fk_visit
                ) ix;