Увеличить скорость запроса - PullRequest
1 голос
/ 29 марта 2012

Использование 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 ]

3 голосов
/ 29 марта 2012

Левые объединения всегда делают запрос намного медленнее, выполнение этого в нескольких базах данных сделает его еще медленнее.

В OpenQuery также есть Group by и снова один в конце.Возможно, замена OpenQuery на временную таблицу (с индексом для столбцов i.parts и i.pg) ускорит процесс.

2 голосов
/ 29 марта 2012

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

использовать i.pg not in ('60','61','62')

Если вы часто используете параметры, попробуйте использовать направляющие для плана sql

1 голос
/ 29 марта 2012

Лучше избегать работы со связанными серверами, так как это портит временную базу данных и может не только вызвать проблемы с производительностью выполняемых запросов, но и повлиять на производительность базы данных в целом.Поскольку вы работаете с SQL-Server-2008, я бы рекомендовал вместо выполнения межсерверного запроса в процедуре вместо передачи табличной переменной в процедуру.

Чтобы передать табличную переменную в хранимую процедуруСначала вам нужно определить структуру таблицы как новый тип.Например:

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

Затем вы можете добавить это к определению хранимой процедуры.например,

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...