C # executescalar vraiment lent sur une grande table

J'ai un problème avec executescalar étant vraiment lent sur une table avec plus de 200.000 loggings.

La méthode que j'utilise vérifie si un varchar existe dans la table et returnne un nombre pour voir si quelque chose peut être trouvé:

public static bool AlreadyQueued(ssortingng url) { using (SqlConnection connection = new SqlConnection(_connectionSsortingng)) { 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; } } 

Ma table est construite comme ceci:

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

Y a-t-il un moyen de rendre ma méthode C # plus rapide, ou dois-je changer quelque chose dans ma table?

La lenteur est dans la database, comme cela a déjà été signalé par d'autres. Puisque vous n'avez pas vraiment besoin du nombre exact, mais plutôt d'un boolean indiquant si une ligne existe ou non, vous pouvez get une légère augmentation des performances comme ceci:

 SELECT TOP 1 1 from PriorityQueue where absolute_url = @url 

Avec cette requête, la database peut arrêter la search une fois que la première correspondance (et vraisemblablement seulement) est trouvée.

Mais pour get des gains de performance significatifs, vous devez append un index à la colonne absolute_url . Mais cette colonne est actuellement définie comme varchar(900) qui est (si j'ai googlé correctement) juste à la limite de combien de time une colonne peut être dans un index. Si vous l'indexez comme tel, l'index prendra à peu près la même quantité d'espace que la table elle-même.

Donc, si possible, raccourcissez la colonne, puis ajoutez un index dessus. Si vous ne pouvez absolument pas le raccourcir, vous pouvez peut-être append une autre colonne qui contient les 50 premiers caractères (par exemple) des colonnes, puis indexer cette colonne à la place. Alors vous pouvez faire comme ceci:

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

Ensuite, vous devez également append le paramètre @shortenedUrl qui doit (bien sûr) contenir les 50 premiers caractères de l'URL que vous searchz.

ExecuteScalar () est utilisé uniquement pour exécuter votre requête, vos données de récupération sont plus que cela prend plus de time.

SQL Count est toujours lent avec un grand nombre d'loggings. S'il vous plaît chercher des options alternatives. Vous pouvez utiliser si Existe ou toute autre option selon vos besoins.

Voici quelques liens qui vous aideront à le comprendre.

Le nombre de SQL Server est lent

Nombre de SQL (*)

SQL Server – Accélérer le comptage sur une grande table

Une sélection de 20 000 lignes sera toujours un peu lente, il peut être judicieux de revoir vos index et d'exécuter AlreadyQueued dans un worker d'arrière-plan.

https://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker(v=vs.110).aspx

Avez-vous essayé "SELECT TOP 1 queueID from PriorityQueue where absolute_url = @url" place? Il devrait y avoir une amélioration notable des performances.

Dans tous les cas, je vous suggère d'append une procédure stockée à votre database pour returnner la valeur booleanne que vous désirez

 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 

Vous pouvez ensuite le tester comme ceci:

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