簡體   English   中英

SQL查詢的執行時間很快,但是獲取行的速度很慢

[英]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個客戶聯系人中給定行的記錄數。 客戶表與客戶聯系人是一對一的。

現在我的問題是:

  1. Sybase為何報告執行時間為0.328秒,但實際上要花費近30秒才能檢索查詢中的行?

  2. 我該怎么做才能優化此查詢?

我的第一個想法是將索引添加到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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM