自最近一次我们数据库的更新以来,我们遇到了一个问题(我是做这个更新的人,我有罪),其中一个查询自那时起就变得慢了很多。 我试图修改查询以获得更快的结果,并设法通过临时表达到了目标,这不错,但我无法理解为什么这种解决方案比基于CTE的解决方案表现更好,这两种方案执行相同的查询。 也许是因为一些表位于不同的数据库中? 这是执行效果差的查询(在我们的硬件上需要22分钟):
WITH CTE_Patterns AS (
SELECT
PEL.iId_purchased_email_list,
PELE.sEmail
FROM OtherDb.dbo.Purchased_Email_List PEL WITH(NOLOCK)
INNER JOIN OtherDb.dbo.Purchased_Email_List_Email AS PELE WITH(NOLOCK) ON PELE.iId_purchased_email_list = PEL.iId_purchased_email_list
WHERE PEL.bPattern = 1
),
CTE_Emails AS (
SELECT
ILE.iId_newsletterservice_import_list,
ILE.iId_newsletterservice_import_list_email,
ILED.sEmail
FROM dbo.NewsletterService_import_list_email AS ILE WITH(NOLOCK)
INNER JOIN dbo.NewsletterService_import_list_email_distinct AS ILED WITH(NOLOCK) ON ILED.iId_newsletterservice_import_list_email_distinct = ILE.iId_newsletterservice_import_list_email_distinct
WHERE ILE.iId_newsletterservice_import_list = 1000
)
SELECT I.iId_newsletterservice_import_list,
I.iId_newsletterservice_import_list_email,
BL.iId_purchased_email_list
FROM CTE_Patterns AS BL WITH(NOLOCK)
INNER JOIN CTE_Emails AS I WITH(NOLOCK) ON I.sEmail LIKE BL.sEmail
当分别运行CTE查询时,速度非常快(在SSMS中为0秒,返回122行和13k行),但在完整查询中使用sEmail
的INNER JOIN时速度非常慢(22分钟)。
以下是执行良好、使用临时表并且完成相同操作、返回相同结果的查询:
SELECT
PEL.iId_purchased_email_list,
PELE.sEmail
INTO #tb1
FROM OtherDb.dbo.Purchased_Email_List PEL WITH(NOLOCK)
INNER JOIN OtherDb.dbo.Purchased_Email_List_Email PELE ON PELE.iId_purchased_email_list = PEL.iId_purchased_email_list
WHERE PEL.bPattern = 1
SELECT
ILE.iId_newsletterservice_import_list,
ILE.iId_newsletterservice_import_list_email,
ILED.sEmail
INTO #tb2
FROM dbo.NewsletterService_import_list_email AS ILE WITH(NOLOCK)
INNER JOIN dbo.NewsletterService_import_list_email_distinct AS ILED ON ILED.iId_newsletterservice_import_list_email_distinct = ILE.iId_newsletterservice_import_list_email_distinct
WHERE ILE.iId_newsletterservice_import_list = 1000
SELECT I.iId_newsletterservice_import_list,
I.iId_newsletterservice_import_list_email,
BL.iId_purchased_email_list
FROM #tb1 AS BL WITH(NOLOCK)
INNER JOIN #tb2 AS I WITH(NOLOCK) ON I.sEmail LIKE BL.sEmail
DROP TABLE #tb1
DROP TABLE #tb2
表格统计信息:
OtherDb.dbo.Purchased_Email_List
:13行,其中2行标记为bPattern
=1OtherDb.dbo.Purchased_Email_List_Email
:324289行,其中122行包含模式(在此问题中使用)dbo.NewsletterService_import_list_email
:1550万行dbo.NewsletterService_import_list_email_distinct
:约150万行WHERE ILE.iId_newsletterservice_import_list = 1000
检索到约13k行
如需更多关于表格的信息,请告知。
能否有人帮我理解这些内容?
更新
以下是CTE查询的查询计划:
以下是使用临时表的查询计划:
WHERE
子句,使得集合变得更小。 - MaxiWheatWITH (NOLOCK)
,而是在会话级别上设置它 - 或者更好的方法是使用 RCSI。 - Aaron Bertrand