提高SQL查询连接14个表的性能

时间:2014-03-06 17:40:49

标签: sql sql-server sql-server-2005

我正在尝试加入14个表,其中我需要使用左连接来连接几个表。 使用大约7000条记录的现有数据,执行以下查询需要大约10秒。如果记录超过百万,我担心怎么办。请帮助我提高以下查询的性能。

CREATE proc [dbo].[GetTodaysActualInvoiceItemSoldHistory]                          
@fromdate datetime,        
@todate datetime        
as                          

Begin                    

select SDID.InvoiceDate as [Sold Date],Cust.custCompanyName as [Sold To] ,   
case SQBD.TransferNo  when '0' then IVM.VendorName else SQBD.TransferNo end as [Purchase From],  
SQBD.BatchSellQty as SoldQty,SQID.SellPrice,  
SDID.InvoiceNo as [Sales Invoice No],INV.PRInvoiceNo as [PO Invoice No],INV.PRInvoiceDate as [PO Invoice Date],   
SQID.ItemDesc as [Item Description],SQID.NetPrice,SDHM.DeliveryHeaderMasterName as   DeliveryHeaderName,    
SQID.ItemCode as [Item Code],           
SQBD.BatchNo,SQBD.ExpiryDate,SQID.Amount,   
SQID.Dept_ID as Dept_ID,              
Dept_Name as [Department],SQID.Catg_ID as Catg_ID,                                    
Category_Name as [Category],SQID.Brand_ID as Brand_ID,               
BrandName as BrandName, SQID.Manf_Id as Manf_Id,                             
Manf.ManfName as [Manufacturer],              
STM.TaxName, SQID.Tax_ID as Tax_ID,              
INV.VendorID as VendorID,              
SQBD.ItemID,SQM.Isdeleted,  
SDHM.DeliveryHeaderMasterID,Cust.CustomerMasterID        
 from  SD_QuotationMaster SQM                  
inner join  SD_InvoiceDetails SDID on SQM.QuoteID = SDID.QuoteID                
inner join  SD_QuoteItemDetails SQID on SDID.QuoteID = SQID.QuoteID               
inner join  SD_QuoteBatchDetails SQBD on SDID.QuoteID = SQBD.QuoteID and SQID.ItemID=SQBD.ItemID              
inner join  INV_ProductInvoice INV on SQBD.InvoiceID=INV.ProductInvoiceID              
inner jOIN  INV_VendorMaster IVM ON INV.VendorID = IVM.VendorID       
inner jOIN  Sys_TaxMaster STM ON SQID.Tax_ID = STM.Tax_ID                 
inner join Cust_CustomerMaster Cust on SQM.CustomerMasterID = Cust.CustomerMasterID    
left jOIN  INV_DeptartmentMaster Dept ON SQID.Dept_ID = Dept.Dept_ID                                       
left jOIN  INV_BrandMaster BRD ON SQID.Brand_ID = BRD.Brand_ID                                       
left jOIN  INV_ManufacturerMaster  Manf ON SQID.Manf_Id = Manf.Manf_Id                
left join INV_CategoryMaster CAT ON SQID.Catg_ID = CAT.Catg_ID                                                              
left join SLRB_DeliveryCustomerMaster SDCM on SQM.CustomerMasterID=SDCM.CustomerMasterID and SQM.DeliveryHeaderMasterID=SDCM.DeliveryHeaderMasterID                                       
left join SLRB_DeliveryHeaderMaster SDHM on SDCM.DeliveryHeaderMasterID=SDHM.DeliveryHeaderMasterID                               
where (SQM.IsDeleted=0)  and SQBD.BatchSellQty > 0          

and SDID.InvoiceDate between @fromdate and @todate                
order by ItemDesc                     

End 

只有下表包含更多数据,而其他表的记录少于20

InvoiceDetails,QuoteMaster,QuoteItemDetails,QuoteBatchDetails ProductInvoice

以下是执行计划的链接

http://jmp.sh/CSZc2x2

感谢。

2 个答案:

答案 0 :(得分:1)

让我们从一个明显的错误开始:

(isnull(SQBD.BatchSellQty,0) > 0)

那个不可索引,所以不应该发生。说真的,在大多数情况下,BatchSellQty不应该是未知的(可空),或者你最好正确地处理null。该字段应该编入索引,我不确定我是否希望使用isNull - 可能有大量的批次。另请注意,过滤后的索引(条件> 0)可能适用于此。

其次,检查您是否拥有所有正确的索引,并且执行计划是有意义的。

你需要测试大量数据。指数统计可能会有所不同。检查时间花在哪里 - 它可能是tempdb,在这种情况下你真的需要一个很好的tempdb IO速度....并且它没有被输入端实现。

答案 1 :(得分:-1)

您可以尝试使用query hints来帮助SQL Server优化程序构建最佳查询执行计划。例如,您可以使用FORCE ORDER语句强制加入表的顺序。如果您按顺序在每个步骤中以最小结果大小进行连接,则查询将执行得更快(可能需要尝试)。例如:

We need to A join B join C
If A join B = 2000 records x 1000 records = ~400 records (we suspect this result)
And A join C = 2000 records x 10 records = ~3 records (and this)
And B join C = 1000 records x 10 records = 10 000 records (and this)

在这种情况下,最佳订单将是

A join C join B = ~3 records x 1000 records = ~3000 records