Je suis tombé sur des articles qui indiquent que SELECT COUNT(*) FROM TABLE_NAME
cela sera lent lorsque le tableau aura beaucoup de lignes et de colonnes.
J'ai une table qui pourrait contenir même des milliards de lignes [elle a environ 15 colonnes]. Existe-t-il un meilleur moyen d'obtenir le compte EXACT du nombre de lignes d'une table?
Veuillez considérer les éléments suivants avant votre réponse:
Je recherche une solution indépendante du fournisseur de base de données. C'est OK s'il couvre MySQL , Oracle , MS SQL Server . Mais s'il n'y a vraiment pas de solution indépendante du fournisseur de base de données, je me contenterai de différentes solutions pour différents fournisseurs de base de données.
Je ne peux utiliser aucun autre outil externe pour ce faire. Je recherche principalement une solution basée sur SQL.
Je ne peux plus normaliser la conception de ma base de données. Il est déjà en 3NF et d'ailleurs beaucoup de code a déjà été écrit autour de lui.
Réponses:
Réponse simple:
COUNT(*)
Remarques:
COUNT (1) = COUNT (*) = COUNT (PrimaryKey) juste au cas où
Éditer:
Exemple SQL Server (1,4 milliard de lignes, 12 colonnes)
1 descente, 5 min 46 s, compte = 1 401 659 700
2 courses, toutes les deux en moins d'une seconde, comptez = 14016596970
Le second a moins de lignes = faux. Serait le même ou plus selon les écritures (les suppressions sont effectuées en dehors des heures ici)
la source
COUNT(*) = COUNT(key)
. C'est tout simplement faux. S'il n'y a pas deNOT NULL
contrainte - alors elles peuvent être différentes (dans les résultats aussi bien que dans le plan d'exécution).index_id < 2
?Le moyen le plus rapide de loin sur MySQL est:
Vous obtiendrez instantanément toutes vos tables avec le nombre de lignes (qui est le total) ainsi que de nombreuses informations supplémentaires si vous le souhaitez.
la source
Cela dépend de la base de données. Certains accélèrent le décompte, par exemple en gardant une trace de si des lignes sont vivantes ou mortes dans l'index, permettant une analyse d'index uniquement pour extraire le nombre de lignes. D'autres ne le font pas et nécessitent par conséquent de visiter la table entière et de compter les lignes en direct une par une. Soit sera lent pour une immense table.
Notez que vous pouvez généralement extraire une bonne estimation en utilisant des outils d'optimisation de requête, des statistiques de table, etc. Dans le cas de PostgreSQL, par exemple, vous pouvez analyser la sortie de
explain count(*) from yourtable
et obtenir une estimation assez bonne du nombre de lignes. Ce qui m'amène à votre deuxième question.Sérieusement? :-) Vous voulez vraiment dire le nombre exact d'une table avec des milliards de lignes? Êtes-vous vraiment sûr? :-)
Si vous le faites vraiment , vous pouvez garder une trace du total à l'aide de déclencheurs, mais faites attention à la simultanéité et aux blocages si vous le faites.
la source
Pour répondre simplement à votre question, non .
Si vous avez besoin d'une méthode indépendante du SGBD pour ce faire, la méthode la plus rapide sera toujours:
Certains fournisseurs de SGBD peuvent avoir des moyens plus rapides qui ne fonctionneront que pour leurs systèmes. Certaines de ces options sont déjà publiées dans d'autres réponses.
COUNT(*)
devrait être optimisé par le SGBD (au moins toute base de données digne de PROD) de toute façon, alors n'essayez pas de contourner leurs optimisations.En passant:
je suis sûr que beaucoup de vos autres requêtes prennent également beaucoup de temps à terminer en raison de la taille de votre table. Tout problème de performances doit probablement être résolu en réfléchissant à la conception de votre schéma en pensant à la vitesse. Je sais que vous avez dit que ce n'était pas une option à changer, mais il se pourrait que les requêtes de plus de 10 minutes ne soient pas non plus une option. La 3e NF n'est pas toujours la meilleure approche lorsque vous avez besoin de vitesse, et parfois les données peuvent être partitionnées dans plusieurs tables si les enregistrements ne doivent pas être stockés ensemble. Quelque chose à quoi penser...
la source
J'ai obtenu ce script d'une autre question / réponse de StackOverflow:
Ma table a 500 millions d'enregistrements et les retours ci-dessus en moins de 1 ms. Pendant ce temps,
prend 39 minutes, 52 secondes!
Ils donnent exactement le même nombre de lignes (dans mon cas, exactement 519326012).
Je ne sais pas si ce serait toujours le cas.
la source
Vous pouvez essayer ce sp_spaceused (Transact-SQL)
la source
Si l'édition de SQL Server est 2005/2008, vous pouvez utiliser des DMV pour calculer le nombre de lignes dans une table:
Pour le moteur de base de données SQL Server 2000, sysindexes fonctionnera, mais il est fortement déconseillé de l'utiliser dans les futures éditions de SQL Server car il pourrait être supprimé dans un avenir proche.
Exemple de code tiré de: Comment obtenir le nombre de lignes de tableau rapidement et sans douleur
la source
j'utilise
la source
Je suis loin d'être aussi expert que d'autres qui ont répondu, mais j'avais un problème avec une procédure que j'utilisais pour sélectionner une ligne au hasard dans un tableau (pas trop pertinent) mais j'avais besoin de connaître le nombre de lignes dans ma table de référence pour calculer l'indice aléatoire. En utilisant le travail traditionnel Count (*) ou Count (1), mais je recevais parfois jusqu'à 2 secondes pour que ma requête s'exécute. Donc à la place (pour ma table nommée 'tbl_HighOrder') j'utilise:
Cela fonctionne très bien et les temps de requête dans Management Studio sont nuls.
la source
Eh bien, en retard de 5 ans et je ne sais pas si cela aide:
J'essayais de compter le non. de lignes dans une table SQL Server à l'aide de MS SQL Server Management Studio et a rencontré une erreur de débordement, puis j'ai utilisé ce qui suit:
sélectionnez count_big (1) FROM [dbname]. [dbo]. [FactSampleValue];
Le résultat :
24296650578 rangées
la source
J'ai trouvé ce bon article SQL Server - COMMENT FAIRE: récupérer rapidement le nombre de lignes exactes pour la table à partir de
martijnh1
laquelle donne un bon récapitulatif pour chaque scénario.J'ai besoin que cela soit développé là où je dois fournir un compte basé sur une condition spécifique et quand je figurerai cette partie, je mettrai à jour cette réponse plus loin.
En attendant, voici les détails de l'article:
Méthode 1:
Requete:
Commentaires:
Effectue une analyse complète de la table. Lent sur les grandes tables.
Méthode 2:
Requete:
Commentaires:
Un moyen rapide de récupérer le nombre de lignes. Dépend des statistiques et est inexact.
Exécutez DBCC UPDATEUSAGE (Database) WITH COUNT_ROWS, ce qui peut prendre beaucoup de temps pour les grandes tables.
Méthode 3:
Requete:
Commentaires:
La façon dont le studio de gestion SQL compte les lignes (regardez les propriétés des tables, le stockage, le nombre de lignes). Très rapide, mais toujours un nombre approximatif de lignes.
Méthode 4:
Requete:
Commentaires:
Fonctionnement rapide (mais pas aussi rapide que la méthode 2) et tout aussi important, fiable.
la source
Je ne pense pas qu'il existe une solution générale toujours la plus rapide: certains SGBDR / versions ont une optimisation spécifique pour
SELECT COUNT(*)
utiliser des options plus rapides tandis que d'autres se contentent de scanner les tables. Vous devez vous rendre sur les sites de documentation / support du second ensemble, qui nécessiteront probablement une requête plus spécifique pour être écrite, généralement une requête qui atteint un index d'une manière ou d'une autre.ÉDITER:
Voici une pensée qui pourrait fonctionner, selon votre schéma et la distribution des données: avez-vous une colonne indexée qui fait référence à une valeur croissante, un ID croissant numérique, par exemple, ou même un horodatage ou une date? Ensuite, en supposant que les suppressions ne se produisent pas, il devrait être possible de stocker le nombre jusqu'à une valeur récente (date d'hier, valeur d'ID la plus élevée à un point d'échantillonnage récent) et d'ajouter le nombre au-delà, ce qui devrait se résoudre très rapidement dans l'index . Très dépendant des valeurs et des indices, bien sûr, mais applicable à presque toutes les versions de n'importe quel SGBD.
la source
SELECT COUNT(*)
. Même MySQL le fait apparemment ....Je suis en retard à cette question, mais voici ce que vous pouvez faire avec MySQL (car j'utilise MySQL). Je partage mes observations ici:
Résultat
Nombre de lignes: 508534
Sortie console : Lignes affectées: 0 Lignes trouvées: 1 Avertissements: 0 Durée pour 1 requête: 0,125 sec.
Prend un certain temps pour une table avec un grand nombre de lignes, mais le nombre de lignes est très exact.
Résultat
Nombre de lignes: 511235
Sortie console : Lignes affectées: 0 Lignes trouvées: 1 Avertissements: 0 Durée pour 1 requête: 0,250 s Résumé: Le nombre de lignes n'est pas exact.
Résultat
Nombre de lignes: 507806
Sortie console : Lignes affectées: 0 Lignes trouvées: 48 Avertissements: 0 Durée pour 1 requête: 1,701 sec.
Le nombre de lignes n'est pas exact.
Je ne suis pas un expert de MySQL ou de base de données, mais j'ai trouvé que pour les très grandes tables, vous pouvez utiliser l'option 2 ou 3 et avoir une «bonne idée» du nombre de lignes présentes.
J'avais besoin d'obtenir ces nombres de lignes pour afficher certaines statistiques sur l'interface utilisateur. Avec les requêtes ci-dessus, je savais que le nombre total de lignes était supérieur à 500 000, j'ai donc proposé des statistiques telles que "Plus de 500 000 lignes" sans afficher le nombre exact de lignes.
Peut-être que je n'ai pas vraiment répondu à la question du PO, mais je partage ce que j'ai fait dans une situation où de telles statistiques étaient nécessaires. Dans mon cas, montrer les lignes approximatives était acceptable et donc ce qui précède a fonctionné pour moi.
la source
Pas exactement une solution indépendante du SGBD, mais au moins votre code client ne verra pas la différence ...
Créez une autre table T avec une seule ligne et un champ entier N 1 , et créez INSERT TRIGGER qui exécute simplement:
Créez également un DELETE TRIGGER qui exécute:
Un SGBD digne de ce nom garantira l'atomicité des opérations au-dessus de 2 , et N contiendra le nombre précis de lignes à tout moment, ce qui est alors très rapide à obtenir simplement:
Bien que les déclencheurs soient spécifiques au SGBD, la sélection entre T ne l'est pas et votre code client n'aura pas besoin de changer pour chaque SGBD pris en charge.
Cependant, cela peut avoir des problèmes d'évolutivité si la table nécessite beaucoup INSERT ou DELETE, en particulier si vous ne COMMITZ PAS immédiatement après INSERT / DELETE.
1 Ces noms ne sont que des espaces réservés - utilisez quelque chose de plus significatif dans la production.
2 Ie N ne peut pas être modifié par une transaction simultanée entre la lecture et l'écriture sur N, tant que la lecture et l'écriture sont effectuées dans une seule instruction SQL.
la source
Une réponse littéralement folle, mais si vous avez mis en place une sorte de système de réplication (pour un système avec un milliard de lignes, je l'espère), vous pouvez utiliser un estimateur approximatif (comme
MAX(pk)
), divisez cette valeur par le nombre d'esclaves vous avez, exécutez plusieurs requêtes en parallèle.Pour la plupart, vous partitionneriez les requêtes entre les esclaves en fonction de la meilleure clé (ou de la clé primaire, je suppose), de cette manière (nous allons utiliser 250000000 comme lignes / esclaves):
Mais vous n'avez besoin que de SQL. Quel buste. Ok, alors disons que tu es un sadomasochiste. Sur le maître (ou l'esclave le plus proche), vous auriez probablement besoin de créer une table pour cela:
Ainsi, au lieu d'avoir uniquement les sélections en cours d'exécution dans vos esclaves, vous devriez faire un insert, semblable à ceci:
Vous pouvez rencontrer des problèmes avec les esclaves écrivant sur une table sur le maître. Vous devrez peut-être devenir encore plus sadique - je veux dire, créatif:
Vous devriez finalement avoir un esclave qui existe en dernier dans le chemin parcouru par le graphe de réplication, par rapport au premier esclave. Cet esclave devrait maintenant avoir toutes les autres contre-valeurs et devrait avoir ses propres valeurs. Mais au moment où vous avez terminé, il y a probablement des lignes ajoutées, vous devrez donc en insérer une autre compensant le max pk enregistré dans votre counter_table et le max pk actuel.
À ce stade, vous devez effectuer une fonction d'agrégation pour déterminer le nombre total de lignes, mais c'est plus facile car vous l'exécuterez sur au plus le "nombre d'esclaves que vous avez et modifiez".
Si vous êtes dans la situation où vous avez des tables séparées dans les esclaves, vous pouvez
UNION
obtenir toutes les lignes dont vous avez besoin.Ou vous savez, soyez un peu moins fou et migrez vos données vers un système de traitement distribué, ou utilisez peut-être une solution de Data Warehousing (qui vous donnera également de superbes données à l'avenir).
Notez que cela dépend de la façon dont votre réplication est configurée. Étant donné que le principal goulot d'étranglement sera probablement un stockage persistant, si vous avez un stockage cruddy ou des magasins de données mal séparés avec un bruit de voisin élevé, cela vous exécutera probablement plus lentement que d'attendre un seul
SELECT COUNT(*) ...
Mais si vous avez une bonne réplication, vos gains de vitesse doivent être directement liés au nombre ou aux esclaves. En fait, s'il faut 10 minutes pour exécuter la requête de comptage seule et que vous avez 8 esclaves, vous réduisez votre temps à moins de quelques minutes. Peut-être une heure pour aplanir les détails de cette solution.
Bien sûr, vous n'obtiendrez jamais vraiment une réponse incroyablement précise car cette résolution distribuée introduit un peu de temps où les lignes peuvent être supprimées et insérées, mais vous pouvez essayer d'obtenir un verrou distribué des lignes dans la même instance et obtenir un nombre précis des lignes du tableau à un moment donné.
En fait, cela semble impossible, car vous êtes essentiellement bloqué avec une solution SQL uniquement, et je ne pense pas que vous disposiez d'un mécanisme pour exécuter une requête fragmentée et verrouillée sur plusieurs esclaves, instantanément. Peut-être que si vous contrôliez le fichier journal de réplication ... ce qui signifie que vous feriez littéralement tourner des esclaves à cette fin, ce qui est sans doute plus lent que d'exécuter la requête de comptage sur une seule machine de toute façon.
Il y a donc mes deux sous en 2013.
la source
Si le déclencheur d'insertion est trop coûteux à utiliser, mais qu'un déclencheur de suppression peut être proposé, et qu'il y a une incrémentation automatique
id
, après avoir compté une fois la table entière et se souvenir du compte commelast-count
etlast-counted-id
,puis chaque jour il suffit de compter pour
id
>last-counted-id
, d'ajouter cela àlast-count
et de stocker le nouveaulast-counted-id
.Le déclencheur de suppression décrémenterait le dernier compte, si l'ID de l'enregistrement supprimé <= le dernier ID compté.
la source
Si vous avez une structure de table typique avec une colonne de clé primaire à incrémentation automatique dans laquelle les lignes ne sont jamais supprimées, ce qui suit sera le moyen le plus rapide pour déterminer le nombre d'enregistrements et devrait fonctionner de manière similaire dans la plupart des bases de données conformes à ANSI:
Je travaille avec des tables MS SQL contenant des milliards de lignes qui nécessitent des temps de réponse inférieurs à la seconde pour les données, y compris le nombre d'enregistrements. Un SELECT COUNT (*) similaire prendrait quelques minutes à comparer.
la source
INSERT
transaction est annulée? Cette valeur de clé primaire serait absente, de sorte que le nombre d'enregistrements réel serait inférieur de un à la valeur maximale.count(*)
si un fournisseur de base de données n'a pas suffisamment optimisécount(*)
: chaque jour, gardez une trace du dernier auto-index et de son nombre correspondant, puis demandez un nombre d'enregistrements après cela. Peut également gérerdelete
s si ajouter un déclencheur lors de la suppression qui diminue le total précédent , si l'identifiant de l'enregistrement supprimé <= ce dernier auto-index.Pour le serveur SQL, essayez ceci
la source
sélectionner des lignes dans sysindexes où id = Object_ID ('TableName') et indid <2
la source
Mettez un index sur une colonne. Cela devrait permettre à l'optimiseur d'effectuer une analyse complète des blocs d'index, au lieu d'une analyse complète de la table. Cela réduira considérablement vos coûts d'E / S. Regardez le plan d'exécution avant et après. Mesurez ensuite le temps de l'horloge murale dans les deux sens.
la source
Si vous utilisez Oracle, qu'en est-il (en supposant que les statistiques de la table sont mises à jour):
last_analyzed affichera l'heure de la dernière collecte des statistiques.
la source
Avec PostgreSQL:
la source
Dans SQL Server 2016, je peux simplement vérifier les propriétés de la table, puis sélectionner l'onglet `` Stockage '' - cela me donne le nombre de lignes, l'espace disque utilisé par la table, l'espace d'index utilisé, etc.
la source
database vendor independent solution
. Cela nécessite également une interface graphique et ne peut pas être automatisé. De plus, ce n'est pas plus rapide que COUNT (*)Peut-être un peu en retard mais cela pourrait aider les autres pour MSSQL
la source