Indeks SQL Server - ascending atau descending, apa bedanya?

142

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?

Joshua Carmody
sumber
1
Jebakan indeks
menurun

Jawaban:

139

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 col1menyimpan nilai yang diurutkan col1bersama dengan referensi ke baris.

Karena tabel dikelompokkan, referensi ke baris sebenarnya adalah nilai dari pk. Mereka juga diurutkan dalam setiap nilai col1.

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 col1akan diurutkan secara menurun, tetapi nilai di pkdalam setiap nilai col1akan diurutkan secara menaik.

Artinya query berikut ini:

SELECT  col1, pk
FROM    mytable
ORDER BY
        col1, pk DESC

dapat dilayani ix_mytable_col1_desctetapi tidak oleh ix_mytable_col1.

Dengan kata lain, kolom yang membentuk a CLUSTERED INDEXdi tabel mana pun selalu merupakan kolom tertinggal dari indeks lain di tabel tersebut.

Quassnoi
sumber
1
Ketika Anda mengatakan "bukan untuk ...", apakah yang Anda maksud itu tidak akan berhasil atau kinerjanya akan buruk?
Neil N
5
Maksud saya, indeks tidak akan digunakan untuk kueri. Kueri itu sendiri tentu saja akan berfungsi, tetapi kinerjanya akan buruk.
Quassnoi
1
Di bagian pertama, bukankah seharusnya contoh kedua mengatakan "ORDER BY col1 DESC, col2 DESC"?
Mitch Wheat
71

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 BACKWARDseperti yang dapat dilihat di Rencana Eksekusi. Namun ada sedikit perbedaan bahwa saat ini hanya FORWARDpemindaian yang dapat diparalelkan.

Rencana

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 %% )

masukkan deskripsi gambar di sini

Martin Smith
sumber
Terima kasih Martin untuk TIP hebat ini, ini benar-benar membantu saya dalam pertanyaan peringkat
TheGameiswar
Saya ingin tahu apakah saya memiliki indeks menurun, lalu pilih kolom saya dari tabel saya di mana indexed_column = \ @myvalue lebih cepat ketika \ @myvalue lebih dekat ke nilai maksimum yang mungkin daripada dalam kasus ketika \ @myvalue ditutup ke nilai minimum yang mungkin.
Lajos Arpad
@LajosArpad mengapa orang bisa lebih cepat? Pohon B adalah pohon yang seimbang. Kedalaman pohonnya sama untuk keduanya.
Martin Smith
@MartinSmith kedalamannya sama, tapi saya ragu urutan saudara kandung tidak akan membuat perbedaan
Lajos Arpad
@MartinSmith, jika urutan saudara kandung memiliki sedikit perbedaan dalam performa, menjalankan jutaan pemilihan akan bertambah, belum lagi gabungan multi-dimensi.
Lajos Arpad
8

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.

Michael Haren
sumber