sql >> Databasteknik >  >> RDS >> Sqlserver

Hur sorterar sql-server dina data?

Även om det är bra att undra över hur det kan förklaras att du ofta ser samma ordning, vill jag påpeka att det aldrig är en bra idé att förlita sig på implicit ordning som orsakas av den specifika implementeringen av den underliggande databasmotorn. Med andra ord, det är trevligt att veta varför, men du ska aldrig lita på det. För MS SQL är det enda som tillförlitligt levererar raderna i en viss ordning en explicit ORDER BY klausul.

Inte nog med att olika RDMBS-er beter sig olika, en viss instans kan bete sig annorlunda på grund av en uppdatering (patch). Inte nog med det, även tillståndet för RDBMS-programvaran kan ha en inverkan:en "varm" databas beter sig annorlunda än en "kall", en liten tabell beter sig annorlunda än en stor.

Även om du har bakgrundsinformation om implementeringen (t.ex.:"det finns ett klustrade index, så det är troligt att data kommer att returneras enligt det klustrade indexets ordning"), finns det alltid en möjlighet att det finns en annan mekanism som du gör. inte vet om det gör att raderna returneras i en annan ordning (ex1:"om en annan session precis gjorde en fullständig tabellskanning med en explicit ORDER BY resultatuppsättningen kan ha cachelagrats; en efterföljande fullständig genomsökning kommer att försöka returnera raderna från cachen"; ex2:"a GROUP BY kan implementeras genom att sortera data, vilket påverkar ordningen som raderna returneras"; ex3:"Om alla de valda kolumnerna är i ett sekundärt index som redan är cachelagrat i minnet, kan motorn skanna det sekundära indexet istället för tabellen, returnerar troligen raderna i ordning efter det sekundära indexet").

Här är ett mycket enkelt test som illustrerar några av mina poänger.

Starta först SQL-servern (jag använder 2008). Skapa denna tabell:

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

Undersök tabellen och bevittna att ett klusterindex skapades för att stödja primary keyid kolumn. Till exempel, i sql server management studio, kan du använda trädvyn och navigera till indexmappen under din tabell. Där bör du se ett index, med ett namn som:PK__test_ord__3213E83F03317E3D (Clustered)

Infoga den första raden med denna sats:

insert into test_order(name)
select RAND()

Infoga fler rader genom att upprepa detta påstående 16 gånger:

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

Du bör nu ha 65536 rader:

select COUNT(*) 
from   test_order

Välj nu alla rader utan att använda en beställning genom att:

select *
from   test_order

Med största sannolikhet kommer resultaten att returneras på beställning av primärnyckeln (även om det inte finns någon garanti). Här är resultatet jag fick (som verkligen är i ordning efter primärnyckel):

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

(# är inte en kolumn utan radens ordningsposition i resultatet)

Skapa nu ett sekundärt index på name kolumn:

create index idx_name on test_order(name)

Välj alla rader, men hämta bara name kolumn:

select name
from   test_order

Mest sannolikt kommer resultaten att returneras i ordning av det sekundära indexet idx_name, eftersom frågan kan lösas genom att endast skanna indexet (i.o.w. idx_name är en täckning index). Här är resultatet jag fick, som verkligen är efter name .

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

Välj nu alla kolumner och alla rader igen:

select * 
from test_order

Här är resultatet jag fick:

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

som du kan se, helt annorlunda än första gången vi körde den här frågan. (Det ser ut som att raderna är ordnade efter det sekundära indexet, men jag har ingen förklaring till varför det skulle vara så).

Hur som helst, slutsatsen är - lita inte på implicit ordning. Du kan komma på förklaringar till varför en viss ordning kan observeras, men även då kan du inte alltid förutsäga den (som i det senare fallet) utan att ha ingående kunskap om implementering och körtidstillstånd.



  1. Skapa en utdatafil med fast bredd i platt format från en SQL-fråga

  2. SQL:Hur man lägger till värden enligt indexkolumner

  3. Flask-Migrate upptäcker inte tabeller

  4. Olika planer för identiska servrar