2016-07-29 3 views
0

이 쿼리 가져 오는 데이터가 매우 slow..I 쿼리를 빠르게 할 매우 느리게 가져 오기 ..SQL 선택 쿼리

데이터베이스에서 데이터를 가져 오는 동안 너무 많은 시간이 소요됩니다 즉 .. 그래서 나는 해결책이 필요합니다. .

SELECT DISTINCT 
    ISNULL(V.VendorItemId, 0) AS VendorItemId, 
    ISNULL(V.VendorItemNumber, I.Ord_guide) AS VendorItemNumber, 
    ISNULL(V.VendorItemDescription, I.Pkg_desc) AS VendorItemDescription, 
    Id = (SELECT Min(k.Id) 
      FROM dbo.InvoiceImportDataPrice k 
      WHERE K.Ord_guide = I.Ord_guide 
      AND K.Price = I.Price 
      AND k.Pkg_desc = I.Pkg_desc 
      AND k.Store_name = I.Store_name 
      AND k.InvoiceImportHistoryId = 128), 
    I.InvoiceImportHistoryId, I.Price, 
    ISNULL(V.CurrentPrice, 0) AS CurrentPrice, 
    ISNULL(ISNULL(V.CurrentPrice, 0) - ISNULL(I.Price, 0), 0) AS differencePrice, 
    I.Invoice_No, I.Sold_to, I.Store_name, I.Deliv_date, 
    (CASE WHEN ISNULL(I.Qty_ship, '0') = '0' THEN '-0' ELSE I.Qty_ship END) AS Qty_ship, 
    I.Ship_um, 
    (CASE WHEN ISNULL(I.Qty_ord, '0') = '0' THEN '-0' ELSE I.Qty_ord END) AS Qty_ord, 
    I.Item_no, I.Weight, 
    (CASE WHEN ISNULL(I.Amount, '0') = '0' THEN '-0' ELSE I.Amount END) AS Amount, 
    I.Pkg_desc, I.Tax_amount, I.Ord_guide, 
    (SELECT COUNT(*) 
    FROM dbo.InvoiceImportDataPrice IP 
    WHERE IP.Pkg_desc = V.VendorItemDescription 
     AND IP.Item_no = V.VendorItemNumber 
     AND IP.Price = V.CurrentPrice) AS PriceDiscrepancyCount 
FROM 
    dbo.InvoiceImportDataPrice I 
LEFT JOIN 
    dbo.VendorItems V WITH (NOLOCK) ON V.VendorItemNumber = I.Ord_guide 
WHERE 
    (I.InvoiceImportHistoryId = 128 AND VendorItemDescription != '"Sales Tax"') 
    or 
    (I.InvoiceImportHistoryId = 128 AND ISNULL(V.VendorItemDescription, '') = '') 

내 문제는이 개 하위 쿼리에 있습니다 :

1.

다음

내 SQL Server 쿼리입니다
Id = (SELECT Min(k.Id) 
      FROM dbo.InvoiceImportDataPrice k 
      WHERE K.Ord_guide = I.Ord_guide 
      AND K.Price = I.Price 
      AND k.Pkg_desc = I.Pkg_desc 
      AND k.Store_name = I.Store_name 
      AND k.InvoiceImportHistoryId = 128) 

2.

(SELECT COUNT(*) 
    FROM dbo.InvoiceImportDataPrice IP 
    WHERE IP.Pkg_desc = V.VendorItemDescription 
     AND IP.Item_no = V.VendorItemNumber 
     AND IP.Price = V.CurrentPrice) AS PriceDiscrepancyCount 
+0

마노 색인 너 – Jaihind

+0

그런 식의 코드를 작성합니까? 적절한 형식을 지정하면 작업이 훨씬 쉬워집니다. – jarlh

+0

나는 –

답변

0

가 읽기 쉽게 있도록 내가 코드를 포맷 한 (3210). 더 많은 답변을 원한다면 실행 계획을 제공하십시오.하지만 언뜻보기에는 눈에 띄는 문제가 있습니다.

귀하의 SELECT 진술 내용에 subqueries 명이 포함되어 있지만, 이는 흔히 나쁜 생각이 아닙니다. 그게 정확히 FROM 섹션을위한 것입니다. 이러한 문을 SELECT 문 대신 조인에 subqueries 같이 이동하십시오.

성능이 좋지 않은 이유는 결과 집합의 행당 한 번 실행되기 때문입니다. 조인에 추가하면 합계로 한 번만 실행되므로 SQL에서 집합 기반 방식으로 처리 할 수 ​​있습니다.

다음과 같은 것이 필요합니다 (샘플 데이터가 없으므로 테스트 안 함). 당신의 형식에 관해서

SELECT DISTINCT 
    ISNULL(V.VendorItemId, 0) AS VendorItemId, 
    ISNULL(V.VendorItemNumber, I.Ord_guide) AS VendorItemNumber, 
    ISNULL(V.VendorItemDescription, I.Pkg_desc) AS VendorItemDescription, 
    Id = Sub1.MinID, 
    I.InvoiceImportHistoryId, 
    I.Price, 
    ISNULL(V.CurrentPrice, 0) AS CurrentPrice, 
    ISNULL(ISNULL(V.CurrentPrice, 0) - ISNULL(I.Price, 0), 0) AS differencePrice, 
    I.Invoice_No, 
    I.Sold_to, 
    I.Store_name, 
    I.Deliv_date, 
    (CASE WHEN ISNULL(I.Qty_ship, '0') = '0' THEN '-0' ELSE I.Qty_ship END) AS Qty_ship, 
    I.Ship_um, 
    (CASE WHEN ISNULL(I.Qty_ord, '0') = '0' THEN '-0' ELSE I.Qty_ord END) AS Qty_ord, 
    I.Item_no 
    , I.Weight, 
    (CASE WHEN ISNULL(I.Amount, '0') = '0' THEN '-0' ELSE I.Amount END) AS Amount 
    ,I.Pkg_desc 
    ,I.Tax_amount 
    ,I.Ord_guide 
    ,Sub2.Cnt AS PriceDiscrepancyCount 
FROM 
    dbo.InvoiceImportDataPrice I 
LEFT JOIN 
    dbo.VendorItems V WITH (NOLOCK) ON V.VendorItemNumber = I.Ord_guide 
LEFT JOIN 
     (
      SELECT Ord_Guide, Price, Pkg_desc, Store_name, Min(k.Id) MinID 
      FROM dbo.InvoiceImportDataPrice k 
      WHERE k.InvoiceImportHistoryId = 128 
      GROUP BY Ord_Guide, Price, Pkg_desc, Store_name 
     ) Sub1 
    ON Sub1.Ord_guide = I.Ord_guide 
    AND Sub1.Price = I.Price 
    AND Sub1.Pkg_desc = I.Pkg_desc 
    AND Sub1.Store_name = I.Store_name 

LEFT JOIN 
     (
     SELECT Pkg_desc, Item_no, Price, COUNT(*) Cnt 
     FROM dbo.InvoiceImportDataPrice IP 
     GROUP BY Pkg_desc, Item_no, Price 
     ) Sub2 
    ON Sub2.Pkg_desc = V.VendorItemDescription 
    AND Sub2.Item_no = V.VendorItemNumber 
    AND Sub2.Price = V.CurrentPrice 
WHERE 
    I.InvoiceImportHistoryId = 128 
    AND 
    (V.VendorItemDescription <> '"Sales Tax"' 
    OR 
    V.VendorItemDescription IS NULL 
    OR 
    V.VendorItemDescription = '') 

, 그것은 궁극적으로이 개인 취향의 요인이다 그러나 이것은 당신에게 당신이 목표로해야 무엇의 아이디어를 줄 것이다 등을 들여 쓰기에 관하여 최선의 방법을 따르는 것이 좋습니다. 일단 익숙해지면 디버깅이 훨씬 쉬워집니다.

SQL Statement indentation good practice

+0

선생님 거의 1 분이 걸릴 것입니다 ...하지만 10 초 미만으로하고 싶습니다. 어떻게해야합니까 ??? 어떤 변경이 필요한가요? 대답에 코드를 게시 할 수 있습니까 ?? –

+0

그런 다음 쿼리의 실행 계획을보고 느린 것을 확인하는 방법에 대해 알아야합니다. 인덱스가 될 수도 있지만 비슷한 것일 수도 있습니다. 그러나 실제 실행 계획을 확인해야합니다. –

+0

SARGable이 아니기 때문에 WHERE 절을 변경 했으므로 성능이 향상되는지보십시오. –

0

InvoiceImportDataPrice

클러스터되지 않은, 고유하지 않은, 사용하여 인덱스 필드

Ord_guide 
Price 
Pkg_desc 
Store_name 
Store_name 
InvoiceImportHistoryId 

에 두 인덱스를 시도 도움이 될 수 있습니다 테이블에
Item_no 
Price 
Pkg_desc