Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Comment APPROX_COUNT_DISTINCT() fonctionne dans SQL Server

APPROX_COUNT_DISTINCT() est l'une des nouvelles fonctions introduites dans SQL Server 2019. Cette fonction renvoie le nombre approximatif de valeurs uniques non nulles dans un groupe.

Fondamentalement, vous pouvez l'utiliser pour avoir une idée approximative du nombre de lignes non dupliquées dans une grande table ou un ensemble de résultats. Cela fonctionne de la même manière que le COUNT_BIG() et COUNT() fonctions (lors de l'utilisation de la fonction DISTINCT clause), mais elle renvoie un nombre approximatif plutôt qu'un nombre précis.

APPROX_COUNT_DISTINCT() vise principalement les scénarios de mégadonnées. Il est conçu pour accéder à de grands ensembles de données avec plus d'un million de lignes et pour l'agrégation d'une colonne ou de colonnes qui ont de nombreuses valeurs distinctes. Il est destiné aux scénarios où la réactivité est plus critique que la précision absolue.

Microsoft déclare que l'implémentation de la fonction garantit jusqu'à 2 % de taux d'erreur avec une probabilité de 97 %.

Au moment de la rédaction, APPROX_COUNT_DISTINCT() est une fonctionnalité de préversion publique. Il a été introduit dans SQL Server 2019, qui est également actuellement en préversion.

Notez que Microsoft déclare que les fonctionnalités de préversion ne sont pas destinées à une utilisation en production.

Syntaxe

La syntaxe ressemble à ceci :

APPROX_COUNT_DISTINCT ( expression ) 

L'expression peut être de n'importe quel type, sauf image , variante_sql , texte , ou texte .

Exemple 1 :COUNT() contre APPROX_COUNT_DISTINCT

Voici un exemple de base comparant COUNT() avec APPROX_COUNT_DISTINCT() :

USE WideWorldImporters;
SELECT 
  COUNT(OrderLineId) 'Actual Count',
  COUNT(DISTINCT OrderLineId) 'Actual Distinct Count',
  APPROX_COUNT_DISTINCT(OrderLineId) 'Approx Distinct Count'
FROM Sales.OrderLines;

Résultat :

+----------------+-------------------------+-------------------------+
| Actual Count   | Actual Distinct Count   | Approx Distinct Count   |
|----------------+-------------------------+-------------------------|
| 231412         | 231412                  | 238493                  |
+----------------+-------------------------+-------------------------+

Dans ce cas, le nombre réel et le nombre distinct réel sont les mêmes (cela signifie simplement qu'il n'y avait pas de doublons dans OrderLineId colonne).

Cependant, nous voyons que APPROX_COUNT_DISTINCT() renvoyé une valeur différente. Il faut s'y attendre, car il ne renvoie qu'une approximation.

Exemple 2 - Un nombre plus petit

Dans cet exemple, je spécifie une colonne différente ( Description ) pour compter :

SELECT 
  COUNT(Description) 'Actual Count',
  COUNT(DISTINCT Description) 'Actual Distinct Count',
  APPROX_COUNT_DISTINCT(Description) 'Approx Distinct Count'
FROM Sales.OrderLines;

Résultat :

+----------------+-------------------------+-------------------------+
| Actual Count   | Actual Distinct Count   | Approx Distinct Count   |
|----------------+-------------------------+-------------------------|
| 231412         | 227                     | 226                     |
+----------------+-------------------------+-------------------------+

Dans ce cas, le compte réel et le compte distinct réel sont différents. En effet, la Description la colonne contient beaucoup de valeurs en double.

Nous pouvons voir que APPROX_COUNT_DISTINCT() a toujours renvoyé une valeur différente, mais c'est assez proche.

Comme mentionné, APPROX_COUNT_DISTINCT() est principalement destiné aux grands ensembles de résultats. Les ensembles de résultats plus petits comme ceux-ci s'exécutent rapidement, quelle que soit la fonction que j'utilise.

Vérifiez le type de données

APPROX_COUNT_DISTINCT() renvoie son résultat sous la forme d'un bigint , donc à cet égard, il ressemble plus à COUNT_BIG() qu'il ne l'est pour COUNT() (qui renvoie un int ). Mais confirmons que :

EXEC sp_describe_first_result_set N'SELECT APPROX_COUNT_DISTINCT(OrderLineId) FROM Sales.OrderLines', null, 0;

Résultat (en utilisant la sortie verticale) :

is_hidden                    | 0
column_ordinal               | 1
name                         | NULL
is_nullable                  | 1
system_type_id               | 127
system_type_name             | bigint
max_length                   | 8
precision                    | 19
scale                        | 0
collation_name               | NULL
user_type_id                 | NULL
user_type_database           | NULL
user_type_schema             | NULL
user_type_name               | NULL
assembly_qualified_type_name | NULL
xml_collection_id            | NULL
xml_collection_database      | NULL
xml_collection_schema        | NULL
xml_collection_name          | NULL
is_xml_document              | 0
is_case_sensitive            | 0
is_fixed_length_clr_type     | 0
source_server                | NULL
source_database              | NULL
source_schema                | NULL
source_table                 | NULL
source_column                | NULL
is_identity_column           | 0
is_part_of_unique_key        | NULL
is_updateable                | 0
is_computed_column           | 0
is_sparse_column_set         | 0
ordinal_in_order_by_list     | NULL
order_by_is_descending       | NULL
order_by_list_length         | NULL
tds_type_id                  | 38
tds_length                   | 8
tds_collation_id             | NULL
tds_collation_sort_id        | NULL

Nous pouvons voir que system_type_name est bigint . Cela nous indique que notre requête renvoie ses résultats en tant que bigint type de données, comme prévu. La max_length et précision les valeurs sont également cohérentes avec le bigint type de données.