Sqlserver
 sql >> база данни >  >> RDS >> Sqlserver

Как sql сървърът сортира вашите данни?

Въпреки че е добре да се чудите как може да се обясни, че често виждате един и същ ред, бих искал да отбележа, че никога не е добра идея да разчитате на имплицитния ред, причинен от конкретната реализация на основния двигател на базата данни. С други думи, хубаво е да знаете защо, но никога не трябва да разчитате на това. За MS SQL единственото нещо, което надеждно доставя редовете в определен ред, е изрично ORDER BY клауза.

Не само, че различните RDMBS се държат по различен начин, един конкретен екземпляр може да се държи по различен начин поради актуализация (корекция). Не само това, дори състоянието на софтуера RDBMS може да окаже влияние:"топлата" база данни се държи различно от "студената", малката таблица се държи различно от голямата.

Дори ако имате основна информация за внедряването (напр.:„има клъстерен индекс, следователно е вероятно данните да бъдат върнати по реда на клъстерния индекс“), винаги има възможност да има друг механизъм, който не знаете не знам за това, което води до връщане на редовете в различен ред (пример 1:„ако друга сесия току-що направи пълно сканиране на таблица с изричен ORDER BY наборът от резултати може да е кеширан; последващо пълно сканиране ще се опита да върне редовете от кеша"; ex2:"a GROUP BY може да се приложи чрез сортиране на данните, като по този начин се повлияе на реда, в който се връщат редовете"; ex3:"Ако всички избрани колони са във вторичен индекс, който вече е кеширан в паметта, машината може да сканира вторичния индекс вместо таблицата, най-вероятно връщане на редовете по реда на вторичния индекс").

Ето един много прост тест, който илюстрира някои от моите точки.

Първо, стартирайте SQL сървър (използвам 2008). Създайте тази таблица:

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

Разгледайте таблицата и станете свидетели, че е създаден групиран индекс, за да поддържа primary key на id колона. Например в студио за управление на sql сървър можете да използвате дървовидния изглед и да отидете до папката с индекси под вашата таблица. Там трябва да видите един индекс с име като:PK__test_ord__3213E83F03317E3D (Clustered)

Вмъкнете първия ред с този израз:

insert into test_order(name)
select RAND()

Вмъкнете още редове, като повторите този израз 16 пъти:

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

Сега трябва да имате 65536 реда:

select COUNT(*) 
from   test_order

Сега изберете всички редове, без да използвате ред по:

select *
from   test_order

Най-вероятно резултатите ще бъдат върнати по ред на първичния ключ (въпреки че няма гаранция). Ето резултата, който получих (който наистина е по реда на първичния ключ):

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

(# не е колона, а поредната позиция на реда в резултата)

Сега създайте вторичен индекс на name колона:

create index idx_name on test_order(name)

Изберете всички редове, но извлечете само name колона:

select name
from   test_order

Най-вероятно резултатите ще бъдат върнати по реда на вторичния индекс idx_name, тъй като заявката може да бъде разрешена само чрез сканиране на индекса (i.o.w. idx_name е покритие индекс). Ето резултата, който получих, който наистина е по ред на name .

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

Сега изберете отново всички колони и всички редове:

select * 
from test_order

Ето резултата, който получих:

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

както виждате, доста различно от първия път, когато изпълнихме тази заявка. (Изглежда, че редовете са подредени по вторичния индекс, но нямам обяснение защо трябва да е така).

Както и да е, изводът е - не разчитайте на имплицитния ред. Можете да измислите обяснения защо определен ред може да бъде наблюдаван, но дори и тогава не можете винаги да го предвидите (както в последния случай), без да имате задълбочени познания за изпълнението и състоянието на изпълнение.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Вътрешни елементи на SQL Server:Проблемни оператори Pt. III – Сортове

  2. Какво е STATISTICS PROFILE в SQL Server?

  3. Как да конвертирате низ в дата/час в SQL Server с помощта на CAST()

  4. Средна стойност на множество колони

  5. Изпробвайте тези най-добри практики за наблюдение на база данни на MySQL