提高查询速度

时间:2012-03-29 09:10:59

标签: sql linked-server

使用SQL,SQL server manager 2008,c-sharp.net 4.0和ms visual studio professional 2010:

我一直在为我的程序进行主要查询,到目前为止,它完全符合预期。 唯一的问题是运行所需的时间。

有时候,大约2000条记录可能需要3分钟。

我被要求更快地得到这个查询,但说实话,我不确定我是怎么做的。

查询如下,它使用链接服务器和4个表。 3在一台服务器上,另一台在本地。

USE [ShaftData]
GO
/****** Object:  StoredProcedure [dbo].[GetSalesBuyers]    Script Date: 03/29/2012   10:03:27 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[GetSalesBuyers] 
@Acct varchar(255),
@Cdisc varchar(255),
@bcs varchar(255), 
@From date, 
@Too date
AS
SELECT i.Acct,
   i.Name, 
   i.Document, 
   i.Part, 
   i.Qty, 
   i.Unit, 
   dbo.NEWPareto.Pareto, 
   i.pg,
   dbo.MyPgTable.PgName,
   i.[DateTime],
   i.BinSeqNo,
   i.cdisc,
   i.bcs

FROM   
OPENQUERY(SACBAUTO, 'SELECT dbo.iHeads.acct,
                            dbo.iHeads.name,
                            dbo.iLines.Document,
                            dbo.iLines.Part,
                            dbo.iLines.Pg,
                            dbo.iLines.Qty,
                            dbo.iLines.unit,
                            dbo.iHeads.[DateTime], 
                            dbo.iLines.BinSeqNo, 
                            dbo.Customer.cdisc,
                            dbo.Customer.Bcs
                     FROM Autopart.dbo.iheads INNER JOIN  Autopart.dbo.iLines ON 
                     Autopart.dbo.Iheads.document = autopart.dbo.iLines.document
                     INNER JOIN Autopart.dbo.Customer ON Autopart.dbo.iheads.acct 
                     = Autopart.dbo.customer.keycode
                     GROUP By dbo.iHeads.acct,
                            dbo.iHeads.name,
                            dbo.iLines.Document,
                            dbo.iLines.Part,
                            dbo.iLines.Pg,
                            dbo.iLines.Qty,
                            dbo.iLines.unit,
                            dbo.iHeads.[DateTime],
                            dbo.iLines.BinSeqNo,
                            dbo.Customer.cdisc,
                            dbo.Customer.bcs
                      ') i
left JOIN
dbo.NEWPareto
ON 
i.Part collate SQL_Latin1_General_CP1_CI_AS = dbo.NEWPareto.Part 
left JOIN
dbo.MyPgTable 
ON  
 i.pg collate SQL_Latin1_General_CP1_CI_AS = dbo.MyPgTable.[pGroup]

WHERE

 (i.[DateTime] BETWEEN @From AND @Too)

 AND (@Cdisc > 29 OR i.cdisc = @Cdisc)

 AND(@Acct = '0' 
 OR (@Acct = '1659%' AND i.Acct not Like @Acct) 
 OR (@Acct = '1557%' AND i.Acct Like @Acct)
 OR (@Acct = '18731%' AND i.Acct not Like '1873%' AND i.Acct not Like '1432%') 
 OR (@Acct != '1659%' AND i.Acct Like @Acct)) 

 AND(@bcs = '0' OR i.bcs != @bcs)

 AND i.pg != '60'
 AND i.pg != '61'
 AND i.pg != '62'

 GROUP BY i.Acct,
   i.Name, 
   i.Document, 
   i.Part, 
   i.Qty, 
   i.Unit, 
   dbo.NEWPareto.Pareto, 
   i.pg,
   dbo.MyPgTable.PgName, 
   i.[DateTime],
   i.BinSeqNo,
   i.cdisc,
   i.bcs

正如你可以看到它很长但工作正常,有没有办法大幅度提高速度?或正在使用链接服务器的问题?

感谢大家帮助我解决这个问题,我很乐意为你选择正确的答案,但我不能,所以取而代之的是所有人的选票!

3 个答案:

答案 0 :(得分:3)

左连接总是使查询慢得多,在多个数据库中执行此操作会使其更慢。

OpenQuery中还有一个Group by,最后还有一个。也许用一个临时表替换OpenQuery(在i.parts和i.pg列上有一个索引)会加快速度。

答案 1 :(得分:2)

AND i.pg != '60' AND i.pg != '61' AND i.pg != '62'

使用i.pg not in ('60','61','62')

如果您经常使用参数,请尝试使用sql计划指南

答案 2 :(得分:1)

最好避免使用链接服务器,它会对Temp DB造成严重破坏,不仅会导致正在运行的查询出现性能问题,而且还会影响整个数据库的性能。由于您使用的是SQL-Server-2008,我建议不要在过程中执行跨服务器查询,而是将表变量传递给procudure。

要将表变量传递给存储过程,首先需要将表结构定义为新类型。 e.g:

CREATE TYPE SACBAutoTable AS TABLE 
(    Acct    INT NOT NULL, 
     Name    VARCHAR(50) NOT NULL 
     ...etc
)

然后,您可以将其添加到存储过程定义中。 e.g。

ALTER PROCEDURE [dbo].[GetSalesBuyers] 
      @SABCAutoTable  SACBAutoTable READONLY, 
      @Acct           VARCHAR(255),
      @Cdisc          VARCHAR(255),
      etc

在查询中,您可以更改

SELECT .... FROM OPENQUERY(

SELECT .... FROM @SABCAutoTable ...

最后从c#调用程序:

SqlDataAdapter adapter = new SqlDataAdapter(YourCrossServerQuery, YourLinkedServerConnectionString);
DataTable table = new DataTable();
adapter.Fill(table);

using (SqlConnection connection = new SqlConnection(yourMainServerConnectionString))
{
    using (SqlCommand command = new SqlCommand(YourSP, connection))
    {
        connection.Open();
        command.Parameters.Add(new SqlParameter("@YourTableVariable", table));
        connection.Close();
    }
}

有关将表变量传递给存储过程的更多信息,请参见http://msdn.microsoft.com/en-us/library/bb510489.aspx

如果性能仍然很慢,那么就开始查看索引,以及其他一般性的整理查询,例如将AND != '60' AND != '61'更改为AND NOT IN ('60', '61')