Ketika Anda membuat indeks pada kolom atau jumlah kolom di MS SQL Server (Saya menggunakan versi 2005), Anda dapat menentukan bahwa indeks pada setiap kolom bisa naik atau turun. Saya kesulitan memahami mengapa pilihan ini ada di sini. Menggunakan teknik pengurutan biner, bukankah pencarian juga akan secepat itu? Apa bedanya pesanan mana yang saya pilih?
sql
sql-server
optimization
indexing
Joshua Carmody
sumber
sumber
Jawaban:
Ini terutama penting bila digunakan dengan indeks komposit:
CREATE INDEX ix_index ON mytable (col1, col2 DESC);
dapat digunakan untuk:
SELECT * FROM mytable ORDER BY col1, col2 DESC
atau:
SELECT * FROM mytable ORDER BY col1 DESC, col2
, tetapi tidak untuk:
SELECT * FROM mytable ORDER BY col1, col2
Indeks pada satu kolom dapat digunakan secara efisien untuk mengurutkan dengan kedua cara.
Lihat artikel di blog saya untuk detailnya:
Memperbarui:
Faktanya, ini bisa menjadi masalah bahkan untuk indeks kolom tunggal, meskipun tidak begitu jelas.
Bayangkan sebuah indeks pada kolom tabel yang dikelompokkan:
CREATE TABLE mytable ( pk INT NOT NULL PRIMARY KEY, col1 INT NOT NULL ) CREATE INDEX ix_mytable_col1 ON mytable (col1)
Indeks pada
col1
menyimpan nilai yang diurutkancol1
bersama dengan referensi ke baris.Karena tabel dikelompokkan, referensi ke baris sebenarnya adalah nilai dari
pk
. Mereka juga diurutkan dalam setiap nilaicol1
.Ini berarti bahwa daun indeks sebenarnya diurutkan
(col1, pk)
, dan kueri ini:SELECT col1, pk FROM mytable ORDER BY col1, pk
tidak perlu disortir.
Jika kita membuat index sebagai berikut:
CREATE INDEX ix_mytable_col1_desc ON mytable (col1 DESC)
, maka nilai
col1
akan diurutkan secara menurun, tetapi nilai dipk
dalam setiap nilaicol1
akan diurutkan secara menaik.Artinya query berikut ini:
SELECT col1, pk FROM mytable ORDER BY col1, pk DESC
dapat dilayani
ix_mytable_col1_desc
tetapi tidak olehix_mytable_col1
.Dengan kata lain, kolom yang membentuk a
CLUSTERED INDEX
di tabel mana pun selalu merupakan kolom tertinggal dari indeks lain di tabel tersebut.sumber
Untuk indeks kolom tunggal yang sebenarnya, ini membuat sedikit perbedaan dari sudut pandang Pengoptimal Kueri.
Untuk definisi tabel
CREATE TABLE T1( [ID] [int] IDENTITY NOT NULL, [Filler] [char](8000) NULL, PRIMARY KEY CLUSTERED ([ID] ASC))
Kueri
SELECT TOP 10 * FROM T1 ORDER BY ID DESC
Menggunakan pemindaian berurutan dengan arah pemindaian
BACKWARD
seperti yang dapat dilihat di Rencana Eksekusi. Namun ada sedikit perbedaan bahwa saat ini hanyaFORWARD
pemindaian yang dapat diparalelkan.Namun itu dapat membuat perbedaan besar dalam hal fragmentasi logis . Jika indeks dibuat dengan kunci menurun tetapi baris baru ditambahkan dengan nilai kunci menaik maka Anda dapat berakhir dengan setiap halaman keluar dari urutan logis. Hal ini dapat sangat memengaruhi ukuran IO yang dibaca saat memindai tabel dan tidak ada dalam cache.
Lihat hasil fragmentasi
avg_fragmentation avg_fragment name page_count _in_percent fragment_count _size_in_pages ------ ------------ ------------------- ---------------- --------------- T1 1000 0.4 5 200 T2 1000 99.9 1000 1
untuk script di bawah ini
/*Uses T1 definition from above*/ SET NOCOUNT ON; CREATE TABLE T2( [ID] [int] IDENTITY NOT NULL, [Filler] [char](8000) NULL, PRIMARY KEY CLUSTERED ([ID] DESC)) BEGIN TRAN GO INSERT INTO T1 DEFAULT VALUES GO 1000 INSERT INTO T2 DEFAULT VALUES GO 1000 COMMIT SELECT object_name(object_id) AS name, page_count, avg_fragmentation_in_percent, fragment_count, avg_fragment_size_in_pages FROM sys.dm_db_index_physical_stats(db_id(), object_id('T1'), 1, NULL, 'DETAILED') WHERE index_level = 0 UNION ALL SELECT object_name(object_id) AS name, page_count, avg_fragmentation_in_percent, fragment_count, avg_fragment_size_in_pages FROM sys.dm_db_index_physical_stats(db_id(), object_id('T2'), 1, NULL, 'DETAILED') WHERE index_level = 0
Anda dapat menggunakan tab hasil spasial untuk memverifikasi anggapan bahwa ini karena halaman selanjutnya memiliki nilai kunci yang naik dalam kedua kasus.
SELECT page_id, [ID], geometry::Point(page_id, [ID], 0).STBuffer(4) FROM T1 CROSS APPLY sys.fn_PhysLocCracker( %% physloc %% ) UNION ALL SELECT page_id, [ID], geometry::Point(page_id, [ID], 0).STBuffer(4) FROM T2 CROSS APPLY sys.fn_PhysLocCracker( %% physloc %% )
sumber
Urutan pengurutan penting saat Anda ingin mengambil banyak data yang diurutkan, bukan rekaman individual.
Perhatikan bahwa (seperti yang Anda sarankan dengan pertanyaan Anda) urutan sortir biasanya jauh kurang signifikan daripada kolom yang Anda indeks (sistem dapat membaca indeks secara terbalik jika urutannya berlawanan dengan yang diinginkannya). Saya jarang memikirkan urutan indeks, sedangkan saya menderita karena kolom yang dicakup oleh indeks.
@Quassnoi memberikan contoh yang bagus tentang kapan hal itu penting.
sumber