【问题标题】:Slow two-table query in SQL ServerSQL Server 中的慢速两表查询
【发布时间】:2017-08-18 23:21:49
【问题描述】:

我使用的应用程序生成的 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)'

&lt;...&gt; 代表一长串 id。列表的大小取决于先前查询的结果,进而取决于为生成该查询而选择的参数。

ID 列表的长度可以是 100 到 2000 以上。

INSURANCE 表很大,超过 900 万行。访问表也很大,但没有那么大。

随着 ID 数量的增加,持续时间从不到一秒增加到超过 15 分钟。增加从大约 175 个 id 开始。

如果更改用于生成查询的参数,使得INS_PAYOR 列未被选中,从而没有左连接,则查询将在不到一秒的时间内运行,即使列表中有超过 2000 个项目身份证。

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

我怎样才能重做这个查询,以减少可怕的延迟来获得相同的结果?

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

谢谢

【问题讨论】:

  • 很可能是 IN() 条件较慢,而不是加入两个表。
  • 可能是这样,但是当尝试使用 IN 条件但没有加入时,结果时间从超过 15 分钟下降到不到 1 秒。这是现场实测。我不能轻易尝试加入但没有 IN,所以我怀疑是两者一起减慢了速度

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


【解决方案1】:

<...> 代表一长串 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

【讨论】:

  • 那会是个问题。我不会说这是不可能的,但之前的查询结果目前在用于生成最终查询之前会以多种方式进行处理(主要是排除项目)。两者之间还有用户确认。不过谢谢你的建议。
【解决方案2】:

使用以下方法查看是否有任何改进...

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;

【讨论】:

  • 谢谢。这看起来很有道理。我会试试看结果如何。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-30
  • 1970-01-01
相关资源
最近更新 更多