如何改善 SQL 哈希匹配右外连接的服务器性能问题
How to improve SQL Server performance issue with hash match right outer join
我不熟悉性能问题。所以我不确定我的方法应该是什么。
这是 运行 花费 7 分钟的查询。
INSERT INTO SubscriberToEncounterMapping(PatientEncounterID, InsuranceSubscriberID)
SELECT
PV.PatientVisitId AS PatientEncounterID,
InsSub.InsuranceSubscriberID
FROM
DB1.dbo.PatientVisit PV
JOIN
DB1.dbo.PatientVisitInsurance PVI ON PV.PatientVisitId = PVI.PatientVisitId
JOIN
DB1.dbo.PatientInsurance PatIns on PatIns.PatientInsuranceId = PVI.PatientInsuranceId
JOIN
DB1.dbo.PatientProfile PP On PP.PatientProfileId = PatIns.PatientProfileId
LEFT OUTER JOIN
DB1.dbo.Guarantor G ON PatIns.PatientProfileId = G.PatientProfileId
JOIN
Warehouse.dbo.InsuranceSubscriber InsSub ON InsSub.InsuranceCarriersID = PatIns.InsuranceCarriersId
AND InsSub.OrderForClaims = PatIns.OrderForClaims
AND ((InsSub.GuarantorID = G.GuarantorId) OR (InsSub.GuarantorID IS NULL AND G.GuarantorId IS NULL))
JOIN
Warehouse.dbo.Encounter E ON E.PatientEncounterID = PV.PatientVisitId
执行计划指出有一个
Hash Match Right Outer Join that Cost 89%
查询。
查询中没有右外连接,所以我看不出问题出在哪里。
如何提高查询效率?
这是散列映射的详细信息:
我会根据减少每个连接返回的记录数的能力对连接重新排序。无论哪种连接可以减少返回的数量或记录,都会提高效率。然后执行外连接。此外,table 锁定始终是一个问题,因此添加 with(nolock) 以防止记录被锁定。
也许像这样的东西稍微调整一下就可以了。
INSERT INTO SubscriberToEncounterMapping (
PatientEncounterID
, InsuranceSubscriberID
)
SELECT PV.PatientVisitId AS PatientEncounterID
, InsSub.InsuranceSubscriberID
FROM DB1.dbo.PatientVisit PV WITH (NOLOCK)
INNER JOIN Warehouse.dbo.Encounter E WITH (NOLOCK)
ON E.PatientEncounterID = PV.PatientVisitId
INNER JOIN DB1.dbo.PatientVisitInsurance PVI WITH (NOLOCK)
ON PV.PatientVisitId = PVI.PatientVisitId
INNER JOIN DB1.dbo.PatientInsurance PatIns WITH (NOLOCK)
ON PatIns.PatientInsuranceId = PVI.PatientInsuranceId
INNER JOIN DB1.dbo.PatientProfile PP WITH (NOLOCK)
ON PP.PatientProfileId = PatIns.PatientProfileId
INNER JOIN Warehouse.dbo.InsuranceSubscriber InsSub WITH (NOLOCK)
ON InsSub.InsuranceCarriersID = PatIns.InsuranceCarriersId
AND InsSub.OrderForClaims = PatIns.OrderForClaims
LEFT JOIN DB1.dbo.Guarantor G WITH (NOLOCK)
ON PatIns.PatientProfileId = G.PatientProfileId
AND (
(InsSub.GuarantorID = G.GuarantorId)
OR (
InsSub.GuarantorID IS NULL
AND G.GuarantorId IS NULL
)
)
为了详细说明我的评论,您可以尝试将其分成两个查询,第一个匹配 GuarantorID
,第二个匹配 InsuranceSubscriber
中的 NULL
,以及在 Guarantor
中,或者如果 Guarantor
中的记录完全丢失:
INSERT INTO SubscriberToEncounterMapping(PatientEncounterID, InsuranceSubscriberID)
SELECT PV.PatientVisitId AS PatientEncounterID, InsSub.InsuranceSubscriberID
FROM DB1.dbo.PatientVisit PV
JOIN DB1.dbo.PatientVisitInsurance PVI
ON PV.PatientVisitId = PVI.PatientVisitId
JOIN DB1.dbo.PatientInsurance PatIns
ON PatIns.PatientInsuranceId = PVI.PatientInsuranceId
JOIN DB1.dbo.PatientProfile PP
ON PP.PatientProfileId = PatIns.PatientProfileId
JOIN DB1.dbo.Guarantor G
ON PatIns.PatientProfileId = G.PatientProfileId
JOIN Warehouse.dbo.InsuranceSubscriber InsSub
ON InsSub.InsuranceCarriersID = PatIns.InsuranceCarriersId
AND InsSub.OrderForClaims = PatIns.OrderForClaims
AND InsSub.GuarantorID = G.GuarantorId
JOIN Warehouse.dbo.Encounter E
ON E.PatientEncounterID = PV.PatientVisitId
UNION ALL
SELECT PV.PatientVisitId AS PatientEncounterID, InsSub.InsuranceSubscriberID
FROM DB1.dbo.PatientVisit PV
JOIN DB1.dbo.PatientVisitInsurance PVI
ON PV.PatientVisitId = PVI.PatientVisitId
JOIN DB1.dbo.PatientInsurance PatIns
ON PatIns.PatientInsuranceId = PVI.PatientInsuranceId
JOIN DB1.dbo.PatientProfile PP
ON PP.PatientProfileId = PatIns.PatientProfileId
JOIN Warehouse.dbo.InsuranceSubscriber InsSub
ON InsSub.InsuranceCarriersID = PatIns.InsuranceCarriersId
AND InsSub.OrderForClaims = PatIns.OrderForClaims
AND InsSub.GuarantorID IS NULL
JOIN Warehouse.dbo.Encounter E
ON E.PatientEncounterID = PV.PatientVisitId
WHERE NOT EXISTS
( SELECT 1
FROM DB1.dbo.Guarantor G
WHERE PatIns.PatientProfileId = G.PatientProfileId
AND InsSub.GuarantorID IS NOT NULL
);
我不熟悉性能问题。所以我不确定我的方法应该是什么。
这是 运行 花费 7 分钟的查询。
INSERT INTO SubscriberToEncounterMapping(PatientEncounterID, InsuranceSubscriberID)
SELECT
PV.PatientVisitId AS PatientEncounterID,
InsSub.InsuranceSubscriberID
FROM
DB1.dbo.PatientVisit PV
JOIN
DB1.dbo.PatientVisitInsurance PVI ON PV.PatientVisitId = PVI.PatientVisitId
JOIN
DB1.dbo.PatientInsurance PatIns on PatIns.PatientInsuranceId = PVI.PatientInsuranceId
JOIN
DB1.dbo.PatientProfile PP On PP.PatientProfileId = PatIns.PatientProfileId
LEFT OUTER JOIN
DB1.dbo.Guarantor G ON PatIns.PatientProfileId = G.PatientProfileId
JOIN
Warehouse.dbo.InsuranceSubscriber InsSub ON InsSub.InsuranceCarriersID = PatIns.InsuranceCarriersId
AND InsSub.OrderForClaims = PatIns.OrderForClaims
AND ((InsSub.GuarantorID = G.GuarantorId) OR (InsSub.GuarantorID IS NULL AND G.GuarantorId IS NULL))
JOIN
Warehouse.dbo.Encounter E ON E.PatientEncounterID = PV.PatientVisitId
执行计划指出有一个
Hash Match Right Outer Join that Cost 89%
查询。
查询中没有右外连接,所以我看不出问题出在哪里。
如何提高查询效率?
这是散列映射的详细信息:
我会根据减少每个连接返回的记录数的能力对连接重新排序。无论哪种连接可以减少返回的数量或记录,都会提高效率。然后执行外连接。此外,table 锁定始终是一个问题,因此添加 with(nolock) 以防止记录被锁定。
也许像这样的东西稍微调整一下就可以了。
INSERT INTO SubscriberToEncounterMapping (
PatientEncounterID
, InsuranceSubscriberID
)
SELECT PV.PatientVisitId AS PatientEncounterID
, InsSub.InsuranceSubscriberID
FROM DB1.dbo.PatientVisit PV WITH (NOLOCK)
INNER JOIN Warehouse.dbo.Encounter E WITH (NOLOCK)
ON E.PatientEncounterID = PV.PatientVisitId
INNER JOIN DB1.dbo.PatientVisitInsurance PVI WITH (NOLOCK)
ON PV.PatientVisitId = PVI.PatientVisitId
INNER JOIN DB1.dbo.PatientInsurance PatIns WITH (NOLOCK)
ON PatIns.PatientInsuranceId = PVI.PatientInsuranceId
INNER JOIN DB1.dbo.PatientProfile PP WITH (NOLOCK)
ON PP.PatientProfileId = PatIns.PatientProfileId
INNER JOIN Warehouse.dbo.InsuranceSubscriber InsSub WITH (NOLOCK)
ON InsSub.InsuranceCarriersID = PatIns.InsuranceCarriersId
AND InsSub.OrderForClaims = PatIns.OrderForClaims
LEFT JOIN DB1.dbo.Guarantor G WITH (NOLOCK)
ON PatIns.PatientProfileId = G.PatientProfileId
AND (
(InsSub.GuarantorID = G.GuarantorId)
OR (
InsSub.GuarantorID IS NULL
AND G.GuarantorId IS NULL
)
)
为了详细说明我的评论,您可以尝试将其分成两个查询,第一个匹配 GuarantorID
,第二个匹配 InsuranceSubscriber
中的 NULL
,以及在 Guarantor
中,或者如果 Guarantor
中的记录完全丢失:
INSERT INTO SubscriberToEncounterMapping(PatientEncounterID, InsuranceSubscriberID)
SELECT PV.PatientVisitId AS PatientEncounterID, InsSub.InsuranceSubscriberID
FROM DB1.dbo.PatientVisit PV
JOIN DB1.dbo.PatientVisitInsurance PVI
ON PV.PatientVisitId = PVI.PatientVisitId
JOIN DB1.dbo.PatientInsurance PatIns
ON PatIns.PatientInsuranceId = PVI.PatientInsuranceId
JOIN DB1.dbo.PatientProfile PP
ON PP.PatientProfileId = PatIns.PatientProfileId
JOIN DB1.dbo.Guarantor G
ON PatIns.PatientProfileId = G.PatientProfileId
JOIN Warehouse.dbo.InsuranceSubscriber InsSub
ON InsSub.InsuranceCarriersID = PatIns.InsuranceCarriersId
AND InsSub.OrderForClaims = PatIns.OrderForClaims
AND InsSub.GuarantorID = G.GuarantorId
JOIN Warehouse.dbo.Encounter E
ON E.PatientEncounterID = PV.PatientVisitId
UNION ALL
SELECT PV.PatientVisitId AS PatientEncounterID, InsSub.InsuranceSubscriberID
FROM DB1.dbo.PatientVisit PV
JOIN DB1.dbo.PatientVisitInsurance PVI
ON PV.PatientVisitId = PVI.PatientVisitId
JOIN DB1.dbo.PatientInsurance PatIns
ON PatIns.PatientInsuranceId = PVI.PatientInsuranceId
JOIN DB1.dbo.PatientProfile PP
ON PP.PatientProfileId = PatIns.PatientProfileId
JOIN Warehouse.dbo.InsuranceSubscriber InsSub
ON InsSub.InsuranceCarriersID = PatIns.InsuranceCarriersId
AND InsSub.OrderForClaims = PatIns.OrderForClaims
AND InsSub.GuarantorID IS NULL
JOIN Warehouse.dbo.Encounter E
ON E.PatientEncounterID = PV.PatientVisitId
WHERE NOT EXISTS
( SELECT 1
FROM DB1.dbo.Guarantor G
WHERE PatIns.PatientProfileId = G.PatientProfileId
AND InsSub.GuarantorID IS NOT NULL
);