2016-11-22 3 views
1

Ich habe ein Problem mit executescalar wird wirklich langsam auf einer Tabelle mit über 200.000 Datensätze.C# executedcalar wirklich langsam auf großen Tisch

Die Methode i Kontrollen verwenden, wenn ein varchar in der Tabelle vorhanden ist und gibt einen Zählwert zu sehen, ob etwas gefunden werden kann:

public static bool AlreadyQueued(string url) 
{ 
    using (SqlConnection connection = new SqlConnection(_connectionString)) 
    { 
     SqlCommand cmd = new SqlCommand("SELECT Count(queueID) from PriorityQueue where absolute_url = @url") 
     { 
      Connection = connection, 
      CommandType = CommandType.Text 
     }; 
     cmd.Parameters.AddWithValue("@url", url); 
     connection.Open(); 
     var count = (int)cmd.ExecuteScalar(); 
     return count > 0; 
    } 
} 

ist meine Tabelle wie folgt aufbauen:

CREATE TABLE PriorityQueue 
(
    queueID int IDENTITY(1,1) PRIMARY KEY, 
    absolute_url varchar (900), 
    depth int, 
    priorty int 
); 

Ist Irgendwann, um meine C# -Methode schneller zu machen, oder muss ich etwas in meiner Tabelle ändern?

+1

Versuchen einen Index für URL-Spalte auf die Tabelle um – Praveen

+0

Es ist nicht, dass Ihre Methode ist langsam. Es ist Ihre Frage, die lange Zeit braucht. Sie können einen Index für 'absolute_url' hinzufügen, um es etwas schneller zu machen, aber für eine große Tabelle wird es eine Weile dauern. –

+0

Auch wenn Sie diese Abfrage häufig mit verschiedenen URLs verwenden, ist es besser, die Add-Methode zu verwenden, um Ihren Parameter zu definieren. Mit der Add-Methode können Sie den Typ und die Größe des Parameters angeben. Insbesondere die Verwendung der Size-Eigenschaft (= 100) hilft dem Database engine optimizer, den Abfrageplan wiederzuverwenden und Dinge auf der Datenbankseite zu beschleunigen. – Steve

Antwort

1

Die Langsamkeit in der Datenbank ist, wie bereits von anderen darauf hingewiesen wurde. Da Sie die genaue Anzahl nicht wirklich brauchen, sondern eine Boolesche anzeigt, ob eine Zeile vorhanden ist oder nicht, können Sie eine leichte Leistungssteigerung wie diese:

SELECT TOP 1 1 from PriorityQueue where absolute_url = @url 

Mit dieser Abfrage kann die Datenbank einmal sucht, das erste (und vermutlich einzige) Spiel wird gefunden.

Um jedoch deutliche Leistungssteigerungen zu erzielen, müssen Sie der Spalte absolute_url einen Index hinzufügen. Aber diese Spalte ist derzeit als varchar(900) definiert, was (wenn ich richtig gegoogelt habe) genau an der Grenze liegt, wie lange eine Spalte in einem Index sein darf. Wenn Sie es als solches indexieren, benötigt der Index etwa den gleichen Speicherplatz wie die Tabelle selbst.

Wenn möglich, kürzen Sie die Spalte und fügen Sie einen Index hinzu. Wenn Sie es absolut nicht kürzen können, können Sie vielleicht eine weitere Spalte hinzufügen, die die ersten (sagen wir) 50 Zeichen der Spalten enthält, und dann diese Spalte indizieren. Dann können Sie wie folgt tun:

SELECT TOP 1 1 from PriorityQueue where absolute_url = @url and shortened_url = @shortenedUrl 

Dann müssen Sie auch den @shortenedUrl Parameter hinzufügen, die sollte (natürlich) enthalten die ersten 50 Zeichen der URL die Sie suchen.

+0

Danke das wirklich geholfen, die Leistung zu erhöhen. –

0

ExecuteScalar() wird nur zum Ausführen der Abfrage verwendet, das Abrufen von Daten dauert länger.

0

Haben Sie statt dessen "SELECT TOP 1 queueID from PriorityQueue where absolute_url = @url" ausprobiert? Es sollte eine spürbare Leistungssteigerung geben.

In jedem Fall empfehle ich Ihnen eine gespeicherte Prozedur zur Datenbank hinzufügen, den Booleschen Wert zurückgeben Sie

Create PROCEDURE UrlFound @absolute_url varchar(900) 
AS 
IF (EXISTS(SELECT TOP 1 1 from PriorityQueue where absolute_url = @absolute_url)) 
    RETURN 1 
ELSE 
    RETURN 0; 
GO 

Sie wünschen kann es dann testen Sie wie folgt aus:

DECLARE @result bit 
exec @result = UrlFound 'YourAbsoluteUrl' 
print @result 
Verwandte Themen