SQL Server dizinleri - artan veya azalan, ne fark eder?


138

MS SQL Server'da bir sütun veya sütun sayısı üzerinde bir dizin oluşturduğunuzda (sürüm 2005 kullanıyorum), her sütundaki dizinin artan veya azalan olmasını belirtebilirsiniz. Bu seçimin neden burada olduğunu anlamakta zorlanıyorum. İkili sıralama teknikleri kullanarak, arama her iki şekilde de hızlı olmaz mıydı? Hangi siparişi seçtiğim ne fark eder?


Yanıtlar:


136

Bu öncelikle bileşik indekslerle kullanıldığında önemlidir:

CREATE INDEX ix_index ON mytable (col1, col2 DESC);

şunlardan biri için kullanılabilir:

SELECT  *
FROM    mytable
ORDER BY
        col1, col2 DESC

veya:

SELECT  *
FROM    mytable
ORDER BY
        col1 DESC, col2

, ancak şunlar için değil:

SELECT  *
FROM    mytable
ORDER BY
        col1, col2

Tek bir sütundaki bir dizin, her iki şekilde de sıralama için verimli bir şekilde kullanılabilir.

Ayrıntılar için blogumdaki makaleye bakın:

Güncelleme:

Aslında, bu çok açık olmasa da, tek bir sütun dizini için bile önemli olabilir.

Kümelenmiş bir tablonun sütununda bir dizin düşünün:

CREATE TABLE mytable (
       pk INT NOT NULL PRIMARY KEY,
       col1 INT NOT NULL
)
CREATE INDEX ix_mytable_col1 ON mytable (col1)

Dizini col1sıralı değerlerini tutarcol1 birlikte satır referansları .

Tablo kümelenmiş olduğundan, satırlara yapılan başvurular aslında pk. Ayrıca her değeri içinde sipariş edilir col1.

Bu, dizinin yapraklarının aslında sipariş edildiği (col1, pk)ve şu sorgulama anlamına gelir :

SELECT  col1, pk
FROM    mytable
ORDER BY
        col1, pk

sıralama gerektirmez.

Dizini aşağıdaki gibi oluşturursak:

CREATE INDEX ix_mytable_col1_desc ON mytable (col1 DESC)

, sonra değerleri col1azalan olarak sıralanır, ancak pkher değerinin içindeki değerler col1artan olarak sıralanır.

Bu şu sorgu anlamına gelir:

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

tarafından sunulabilir, ix_mytable_col1_descancak tarafından sunulamaz ix_mytable_col1.

Başka bir deyişle, CLUSTERED INDEXherhangi bir tabloda a'yı oluşturan sütunlar her zaman o tablodaki diğer dizinlerin sondaki sütunlarıdır.


1
"Şunun için değil ..." derken bunun işe yaramayacağını mı yoksa performansın korkunç olacağını mı kastediyorsunuz?
Neil N

5
Dizin, sorgu için kullanılmayacağı anlamına gelir. Sorgunun kendisi elbette işe yarayacaktır, ancak performans düşük olacaktır.
Quassnoi

1
Birinci bölümde, ikinci örnek "ORDER BY col1 DESC, col2 DESC" dememeli mi?
Mitch Wheat

71

Gerçek bir tek sütun dizini için, Sorgu Optimize Edici'nin bakış açısından çok az fark yaratır.

Tablo tanımı için

CREATE TABLE T1( [ID] [int] IDENTITY NOT NULL,
                 [Filler] [char](8000) NULL,
                 PRIMARY KEY CLUSTERED ([ID] ASC))

Sorgu

SELECT TOP 10 *
FROM T1
ORDER BY ID DESC

BACKWARDYürütme Planında görülebildiği gibi, tarama yönüne sahip sıralı bir tarama kullanır . Bununla birlikte, şu anda sadeceFORWARD taramaların paralelleştirilebilmesi bakımından .

Plan

ancak , mantıksal parçalanma açısından büyük bir fark yaratabilir . Dizin azalan tuşlarla oluşturulmuş ancak artan anahtar değerlerine yeni satırlar eklenmişse, her sayfanın mantıksal düzeninden çıkmasıyla sonuçlanabilirsiniz. Bu, tabloyu tararken ES okumalarının boyutunu ciddi şekilde etkileyebilir ve önbellekte değildir.

Parçalanma sonuçlarına bakın

                    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

aşağıdaki senaryo için

/*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 

Bunun, sonraki sayfaların her iki durumda da artan anahtar değerlere sahip olması nedeniyle varsayımını doğrulamak için uzamsal sonuçlar sekmesini kullanmak mümkündür.

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

resim açıklamasını buraya girin


Bu harika İPUCU için teşekkür ederim Martin, bu gerçekten rütbe sorgularında bana yardımcı oldu
TheGameiswar

Azalan bir indeksim var mı diye merak ediyorum, sonra \ @ değerim mümkün olan maksimum değere daha yakın olduğunda \ @ değerim mümkün olan en yüksek değere daha yakın olduğunda dizinli_kolumn = \ @ değerimin daha hızlı olduğu mytable sütununu seçin.
Lajos Arpad

@LajosArpad neden daha hızlı olsun ki? B ağaçları dengeli ağaçlardır. Ağacın derinliği her ikisi için de aynıdır.
Martin Smith

@MartinSmith derinliği aynı, ama kardeşlerin düzeninin bir fark yaratmayacağından şüpheliyim
Lajos Arpad

@MartinSmith, eğer kardeşlerin sırası performansta küçük bir fark olsa bile, o zaman milyonlarca seçim yapmak çok boyutlu birleşimlerden bahsetmeden toplanır.
Lajos Arpad

8

Sıralama sırası, ayrı ayrı kayıtlar değil, çok sayıda sıralanmış veri almak istediğinizde önemlidir.

(Sorunuzda önerdiğiniz gibi) sıralama düzeninin genellikle hangi dizinleri dizine eklediğinizden çok daha az önemli olduğuna dikkat edin (sipariş istediklerinin tersi ise sistem dizini tersine okuyabilir). Ben nadiren dizin sıralama düzeni herhangi bir düşünce verirken, ben dizin tarafından kapsanan sütunlar üzerinde acı.

@Quassnoi bir sağlar büyük bir örnek o ne zaman gelmez önemli.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.