2012-03-29 17 views
1

Verwenden von SQL, SQL-Server-Manager 2008 c-sharp.net 4.0 und MS Visual Studio Professional 2010:Zunahme Speed ​​Of Abfrage

Ich habe für mein Programm auf einer Haupt-Abfrage zu arbeiten, und so weit es funktioniert genau wie beabsichtigt. Das einzige Problem ist die Zeit, die zum Ausführen benötigt wird.

einige Male kann es bis zu 3 Minuten für etwa 2000 Datensätze dauern.

Ich wurde gebeten, diese Abfrage viel schneller zu bekommen, aber in aller Ehrlichkeit bin ich mir nicht sicher, wie ich das kann.

Abfrage ist unten, es verwendet einen Verbindungsserver und 4 Tabellen. 3 auf einem Server und der andere ist lokal.

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 

Wie Sie seine ziemlich lange sehen können, aber funktioniert gut, ist es eine Möglichkeit, drastisch die Geschwindigkeit zu erhöhen? oder arbeitet mit verbundenen Servern das Problem?

Danke an euch alle, dass ihr mir bei dieser Frage geholfen habt, ich würde euch alle gerne für die richtige Antwort auswählen, aber ich kann nicht, also stattdessen Ups für alle!

+0

Dies könnte eine Frage sein besser geeignet für [Code Review] (http://codereview.stackexchange.com/) oder [Datenbankadministratoren] (http://dba.stackexchange.com/) – musefan

+0

Vielleicht lohnt sich, eine zu betrachten Indizes und Schlüssel, die Sie auf Ihren Tischen haben; Sie können möglicherweise effizientere Indizes erstellen, um die Vorgänge zu beschleunigen. – JTeagle

+0

Ich gebe diese Seiten einen Versuch, hatte Hopping meine Abfrage hatte einen Teil, der übersehen wurde, dass viel schneller gemacht werden könnte, weshalb ich fragte, hier. – lemunk

Antwort

3

Linke führt zu verwenden Joins immer eine Abfrage langsamer viel machen, tun dies über mehrere Datenbanken wird es machen noch langsamer.

Es gibt auch eine Gruppe von in der OpenQuery und wieder eine am Ende. Vielleicht würde das Ersetzen der OpenQuery durch eine temporäre Tabelle (mit einem Index für die Spalte i.parts und i.pg) die Dinge beschleunigen.

+0

+1 für die Empfehlung der Verwendung einer temporären Tabelle als Ersatz für Cross-Datenbank-Joins – Seph

+0

gut entdeckt, kann ich nicht wirklich erinnern, warum ich das in die offene Abfrage setzen. Ich habe es nur herausgenommen und mit den gleichen Parametern habe ich die Zeit um mehr als 1min20 Sekunden reduziert ..... wow – lemunk

+0

auch krank haben einen Blick auf die Verwendung von Temp-Tabelle – lemunk

2

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

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

Wenn Sie häufig Parameter dann verwendet haben, versuchen, SQL Plan

+0

vertrauen Sie mir, um die Sodding Basics zu vergessen, yer total vergessen "nicht in" ty – lemunk

+0

Ich glaube nicht, Änderung dieser wird keinen nennenswerten Einfluss auf die Leistung haben – Seph

+0

Diese Werte sollten in der Tat zusammen, aber warum sind sie bei der herausgefiltert Ende? und nicht in der OpenQuery, wo sie viel einfacher herausgefiltert werden könnten. – Lex

1

Die Arbeit mit Verbindungsservern sollte am besten vermieden werden, da sie die Temp-Datenbank verwüstet und nicht nur Leistungsprobleme mit den ausgeführten Abfragen verursachen kann, sondern sich auch auf die gesamte DB-Leistung auswirkt. Da Sie mit SQL-Server-2008 arbeiten, würde ich empfehlen, anstatt die Cross-Server-Abfrage innerhalb der Prozedur auszuführen, stattdessen eine Tabellenvariable an die Prozedur zu übergeben.

Sie zuerst die Tabellenstruktur als eine neue Art definieren müssen eine Tabellenvariable an eine gespeicherte Prozedur übergeben zu. Beispiel:

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

Dann können Sie dies zur gespeicherten Prozedurdefinition hinzufügen. z.B.

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

Weiter in der Abfrage können Sie dann

SELECT .... FROM OPENQUERY(

zu

SELECT .... FROM @SABCAutoTable ...

Schließlich ändern Sie die Prozedur von C# nennen:

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(); 
    } 
} 

Weitere Informationen über Tabellenvariablen für gespeicherte Prozeduren geben können hier http://msdn.microsoft.com/en-us/library/bb510489.aspx

Wenn die Leistung dieses dann noch gefunden werden beginnen langsam auf Indizes suchen, und andere allgemeine Aufraeumen der Abfrage wie AND != '60' AND != '61'-AND NOT IN ('60', '61') Ändern