[英]SQL Query execution time fast, but fetching rows is slow
這是一個兩部分的問題,但首先是一些背景信息:
我在Sybase中有一個TSQL查詢,報告執行時間為0.328秒,但是檢索大約5000行需要大約20-30秒。 該查詢具有兩個子查詢和一個左外部聯接。
查詢大致如下所示:
SELECT CustomerContact.Id, Customer.Name, ...
, CustomerContacts.LastName, CustomerContacts.FirstName
, ( SELECT max(LastModified)
FROM ContactPhone
WHERE ContactPhone.ContactID = CustomerContact.ID
) as PhoneLastModified
, ( SELECT max(LastModified)
FROM ContactEmail
WHERE ContactEmail.ContactID = CustomerContact.ID
) as EmailLastModified
FROM CustomerContacts
LEFT OUTER JOIN Customer
ON Customer.ID = CustomerContact.CustomerId
WHERE (PhoneLastModified > '2011-01-01'
OR EmailLastModified > '2011-01-01')
我正在做的是根據任何關聯的聯系信息的最后修改日期選擇客戶記錄。 ContactPhone和ContactEmail可以包含x個客戶聯系人中給定行的記錄數。 客戶表與客戶聯系人是一對一的。
現在我的問題是:
Sybase為何報告執行時間為0.328秒,但實際上要花費近30秒才能檢索查詢中的行?
我該怎么做才能優化此查詢?
我的第一個想法是將索引添加到LastModified列中,但是我正在處理少量記錄。
我的第二個想法是子查詢正在減慢速度,因此我應該將它們轉換為聯接。 但是我不能在Join條件下使用聚合函數max,那么如何在join中僅獲取max行?
謝謝
我猜想select子句中的2個相關子查詢在返回行之前不會執行。 通常,應避免使用相關的子查詢,因為它們往往很慢,當然總會有例外!
嘗試將ContactPhone和Contact Email移到合並的子查詢中。
SELECT
cc.Id,
c.Name,
... ,
cc.LastName, CustomerContacts.FirstName,
cp.LastModified PhoneLastModified
ce.LastModified EmailLastModified
FROM
CustomerContacts cc
LEFT OUTER JOIN
Customer c
ON
c.ID = cc.CustomerId
INNER JOIN
(SELECT
ContactId,
max(LastModified) as LastModified
FROM
ContactPhone
WHERE
LastModified > '2011-01-01'
GROUP BY
ContactId ) cp
ON
cp.ContactID = cc.ID
INNER JOIN
(SELECT
ContactId,
max(LastModified) as LastModified
FROM
ContactEmail
WHERE
LastModified> '2011-01-01'
GROUP BY
ContactId ) ce
ON
ce.ContactID = cc.ID
我現在知道他使用的是SYBASE而不是SQL Server(也可以是TSQL),但我將把答案留給其他正在使用MS產品的人。
這是CTE版本。 與Paul的版本相同,但更易於閱讀:
WITH MaxContactPhone AS
(
SELECT max(LastModified) as LastModified, ContactID
FROM ContactPhone
WHERE LastModified> '2011-01-01'
GROUP BY ContactID
), MaxContactEmail AS
(
SELECT max(LastModified) as LastModifed, ContactID
FROM ContactEmail
WHERE LastModified> '2011-01-01'
GROUP BY ContactID
)
SELECT CustomerContact.Id, Customer.Name, ... , CustomerContacts.LastName,
CustomerContacts.FirstName,
MaxContactPhone.LastModified as PhoneLastModified,
MaxContactEmail.LastModified as EmailLastModified
FROM CustomerContacts
LEFT OUTER JOIN Customer ON Customer.ID = CustomerContact.CustomerId
JOIN MaxContactPhone ON CustomerContact.CustomerId = MaxContactPhone.ContactID AND
JOIN MaxContactEmail ON CustomerContact.CustomerId = MaxContactEmail.ContactID
SELECT cc.ID, cu.Name, ...
, cc.LastName, cc.FirstName
, g.PhoneLastModified
, g.EmailLastModified
FROM CustomerContacts cc
LEFT JOIN Customer cu
ON cu.ID = cc.CustomerID
JOIN
( SELECT cc.ID
, max(cp.LastModified)
AS PhoneLastModified
, max(ce.LastModified)
AS EmailLastModified
FROM CustomerContacts cc
LEFT JOIN ContactPhone cp
ON cp.ContactID = cc.ID
LEFT JOIN ContactEmail ce
ON ce.ContactID = cc.ID
GROUP BY cc.ID
HAVING ( PhoneLastModified > '2011-01-01'
OR EmailLastModified > '2011-01-01' )
) AS g
ON g.Id = cc.id
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.