SQL选择查询提取非常慢

时间:2016-07-29 08:54:50

标签: sql sql-server

此查询提取数据非常慢..我想加快查询速度..

即。从数据库中获取数据时会花费太多时间。 所以我需要一个解决方案......

这是我的SQL Server查询:

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, '') = '')

我的问题在于2个子查询:

1

    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

2 个答案:

答案 0 :(得分:0)

我已经格式化了代码,因此更容易阅读。如果你想要更多答案,请提供执行计划,但乍看之下,我看到了一个明显的问题。

您的subqueries声明中有SELECT,这些往往是一个非常糟糕的主意。这正是FROM部分的用途。将这些语句作为subqueries移动到连接中而不是SELECT语句中。

这些性能差的原因是它们将在结果集的每一行执行一次。如果你在连接中添加它们,那么它们将只执行一次(总计),这将允许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

答案 1 :(得分:0)

InvoiceImportDataPrice

上试试这两个索引

非群集,非唯一,使用索引字段

Ord_guide
Price 
Pkg_desc
Store_name
Store_name
InvoiceImportHistoryId 

Item_no
Price
Pkg_desc