SQL Where子句大大增加了查询时间

3

我有一张表格,在其上执行了一些联接和操作。这个表格大约有15万行,如果我选择所有行并运行它,大约需要10秒钟返回结果。如果我将我的查询创建为自己的表,并过滤掉某个字段为空的所有行,则现在查询需要10分钟才能运行。这样的情况是否正常,或者有没有办法解决它?以下是查询代码。

SELECT *
FROM
(
    Select 
     I.Date_Created
    ,I.Company_Code
    ,I.Division_Code
    ,I.Invoice_Number
    ,Sh.CUST_PO
    ,I.Total_Quantity
    ,ID.Total
    ,SH.Ship_City City
    ,CASE WHEN SH.Ship_Cntry <> 'US' THEN 'INT' ELSE SH.Ship_prov END State
    ,SH.Ship_Zip Zip
    ,SH.Ship_Cntry Country
    ,S.CustomerEmail
    from [JMNYC-AMTDB].[AMTPLUS].[dbo].Invoices I (nolock)
    LEFT JOIN (SELECT 
                    ID.Company_Code
                    ,ID.Division_Code
                    ,ID.Invoice_Number
                    ,SUM (ID.Price* ID.Quantity) Total
                    FROM [JMNYC-AMTDB].[AMTPLUS].[dbo].Invoices_Detail ID (nolock)
                    GROUP BY ID.Company_Code, ID.Division_Code, ID.Invoice_Number) ID 
            ON I.Company_Code = ID.Company_Code
            AND I.Division_Code = ID.Division_Code
            AND I.Invoice_Number = ID.Invoice_Number
    LEFT JOIN 
        [JMDNJ-ACCELSQL].[A1WAREHOUSE].[dbo].SHIPHIST SH (nolock) ON I.Pickticket_Number = SH.Packslip
    LEFT JOIN 
        [JMDNJ-ACCELSQL].[A1WAREHOUSE].[dbo].[MagentoCustomerEmailData] S on SH.CUST_PO = S.InvoiceNumber

    Where I.Company_Code ='09' AND I.Division_Code = '001'
    AND I.Customer_Number = 'ECOM2X'
    )T
    Where T.CustomerEmail IS NOT NULL -- This is the problematic line
Order By T.Date_Created desc 

我有一个表格,我在其中进行一些连接和操作。看起来你有很多表格和很多操作。不太清楚你具体在问什么,但如果我猜的话,如果你查看中间表格,它会非常非常大。 - Gordon Linoff
3
如果您使用SSMS,请右键单击查询并选择“显示实际执行计划”。然后运行查询。执行计划可能会建议向表添加索引。 - O. Jones
查询正在哪个服务器上运行?[JMNYC-AMTDB]还是[JMDNJ-ACCELSQL]。通常我会避免跨链接服务器连接表。这是必要的吗?你正在处理两个不同服务器上的两个不同查询优化器。您能否先在一个服务器上将数据汇集在一起?没有问题的那一行,服务器只需要返回所有行。当您引入有问题的那一行时,现在您正在要求两个不同的SQL Server优化器(在两个不同的服务器上)创建一个高效的计划。我甚至认为SQL Server都不会这样做,更别说如果它确实这样做了,我也无法告诉您它是如何做到的。 - jamie
@Jamie,很遗憾,链接服务器是必要的。 我已经用完了JMDNJ数据库。 接下来的最佳方式是什么?也许可以从我的结果创建一个新表(它将是静态的),然后将该表添加到我正在使用的主表中(未显示)。 - Natan
1
如果查询在没有问题的情况下正常运行,则添加一步。将结果放入一个没有问题的行的表中,然后查询该新表并在其中添加有问题的筛选器。这将起作用,并且如果这是一次性/临时请求,则应该足够。如果这将成为操作性的,则还有更多需要解决的问题。 - jamie
理想情况下,如果您编写这样的查询,则应在最内部的查询中进行过滤。有什么阻止您将where子句条件放在一起吗?此外,在两种情况下,S.CustomerEmail为NULL:1)左连接在不匹配条件下返回null或2)该日期列接受nulls……因此,最好使用S-别名表上的内部连接,并附加:S.CustomerEmail IS NOT NULL。 - Zorkolot
1个回答

1
如果您已经了解索引考虑事项并且确定问题点,那么您可以使用此方法来改进它:
USE A1WAREHOUSE;
GO

CREATE NONCLUSTERED INDEX IX_MagentoCustomerEmailData_CustomerEmail
ON [dbo].[MagentoCustomerEmailData] (CustomerEmail ASC);

GO

完全地,你需要在使用到 ORDER BYWHEREGROUP BYON 等部分的列上添加索引。在添加索引之前,请确保你已经了解了后果。
更多关于索引的信息:
  1. https://www.mssqltips.com/sqlservertutorial/9133/sql-server-nonclustered-indexes/
  2. https://www.itprotoday.com/sql-server/indexing-dos-and-don-ts

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接