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

Comment le serveur sql trie-t-il vos données ?

Bien qu'il soit bon de se demander comment on pourrait expliquer que vous voyez souvent le même ordre, je tiens à souligner qu'il n'est jamais judicieux de s'appuyer sur un ordre implicite causé par l'implémentation particulière du moteur de base de données sous-jacent. En d'autres termes, c'est bien de savoir pourquoi, mais vous ne devriez jamais vous y fier. Pour MS SQL, la seule chose qui fournit de manière fiable les lignes dans un certain ordre est un ORDER BY explicite clause.

Non seulement différents RDMBS se comportent différemment, mais une instance particulière peut se comporter différemment en raison d'une mise à jour (correctif). Non seulement cela, même l'état du logiciel RDBMS peut avoir un impact :une base de données "chaude" se comporte différemment d'une base de données "froide", une petite table se comporte différemment d'une grande.

Même si vous avez des informations générales sur l'implémentation (ex :"il existe un index clusterisé, il est donc probable que les données seront renvoyées dans l'ordre de l'index clusterisé"), il est toujours possible qu'il existe un autre mécanisme que vous n'avez pas Je ne sais pas pourquoi les lignes sont renvoyées dans un ordre différent (ex1 :"si une autre session vient de faire une analyse complète de la table avec un ORDER BY explicite le jeu de résultats peut avoir été mis en cache ; une analyse complète ultérieure tentera de renvoyer les lignes du cache" ; ex2 :"a GROUP BY peut être implémenté en triant les données, impactant ainsi l'ordre dans lequel les lignes sont renvoyées" ; ex3 :"Si les colonnes sélectionnées sont toutes dans un index secondaire qui est déjà mis en cache en mémoire, le moteur peut scanner l'index secondaire au lieu de la table, renvoyant très probablement les lignes dans l'ordre de l'index secondaire").

Voici un test très simple qui illustre certains de mes propos.

Tout d'abord, démarrez le serveur SQL (j'utilise 2008). Créez ce tableau :

create table test_order (
    id int not null identity(1,1) primary key
,   name varchar(10) not null 
)

Examinez la table et constatez qu'un index cluster a été créé pour prendre en charge la primary key sur l'id colonne. Par exemple, dans sql server management studio, vous pouvez utiliser l'arborescence et accéder au dossier des index sous votre table. Là, vous devriez voir un index, avec un nom comme :PK__test_ord__3213E83F03317E3D (Clustered)

Insérez la première ligne avec cette déclaration :

insert into test_order(name)
select RAND()

Insérez plus de lignes en répétant cette instruction 16 fois :

insert into test_order(name)
select RAND()
from   test_order

Vous devriez maintenant avoir 65536 lignes :

select COUNT(*) 
from   test_order

Maintenant, sélectionnez toutes les lignes sans utiliser de tri par :

select *
from   test_order

Très probablement, les résultats seront renvoyés dans l'ordre de la clé primaire (bien qu'il n'y ait aucune garantie). Voici le résultat que j'ai obtenu (qui est en effet par ordre de clé primaire) :

#      id    name
1      1     0.605831
2      2     0.517251
3      3     0.52326
.      .     .......
65536  65536 0.902214

(le # n'est pas une colonne mais la position ordinale de la ligne dans le résultat)

Maintenant, créez un index secondaire sur le name colonne :

create index idx_name on test_order(name)

Sélectionnez toutes les lignes, mais récupérez uniquement le name colonne :

select name
from   test_order

Très probablement, les résultats seront renvoyés dans l'ordre de l'index secondaire idx_name, car la requête peut être résolue en scannant uniquement l'index (i.o.w. idx_name est une couverture indice). Voici le résultat que j'ai obtenu, qui est en effet par ordre de name .

#      name
1      0.0185732
2      0.0185732
.      .........
65536  0.981894

Maintenant, sélectionnez à nouveau toutes les colonnes et toutes les lignes :

select * 
from test_order

Voici le résultat que j'ai :

#      id    name
1      17    0.0185732
2      18    0.0185732
3      19    0.0185732
...    ..    .........

comme vous pouvez le voir, tout à fait différent de la première fois que nous avons exécuté cette requête. (On dirait que les lignes sont triées par l'index secondaire, mais je n'ai pas d'explication pourquoi il devrait en être ainsi).

Quoi qu'il en soit, l'essentiel est - ne vous fiez pas à l'ordre implicite. Vous pouvez penser à des explications pour lesquelles un ordre particulier peut être observé, mais même dans ce cas, vous ne pouvez pas toujours le prédire (comme dans ce dernier cas) sans avoir une connaissance intime de l'implémentation et de l'état d'exécution.