SQL Server'da sayfalandırma


17

Çok büyük bir veritabanım var, kabaca 100 GB. Sorgu yürütüyorum:

select * from <table_name>;

ve sadece 100. ila 200. sıraları göstermek istiyorum.

Bunun dahili olarak nasıl olduğunu anlamak istiyorum. Veritabanı diskteki tüm kayıtları belleğe alıyor mu ve sorgulama istemcisine 100 ila 400. satırları geri gönderiyor mu? Ya da herhangi bir mekanizma var mı, böylece sadece bu kayıtların (100.-200.) B-ağaçları vb.

Bunun sayfalandırma kavramı ile ilgili olduğunu buldum, ancak tam olarak veritabanı düzeyinde nasıl olduğunu tam olarak bulamadım.

Yanıtlar:


37

Gönderdiğiniz sorguda:

select * from <table_name>;

100.-200. sıralar diye bir şey yoktur, çünkü bir ORDER BY belirtmezsiniz. Bir sürü ilginç nedenden dolayı SİPARİŞİ dahil etmedikçe sipariş garanti edilmez, ancak bu gerçekten önemli değildir.

Yani, noktanızı göstermek için bir tablo kullanalım - Yığın Taşması veri dökümünden Kullanıcılar tablosunu kullanacağım ve bu sorguyu çalıştıracağım:

SELECT * FROM dbo.Users ORDER BY DisplayName;

Varsayılan olarak, DisplayName alanında dizin yoktur, bu nedenle SQL Server'ın tüm tabloyu taraması ve DisplayName'e göre sıralaması gerekir. Uygulama planı :

Bir sıralama ile kümelenmiş dizin taraması

Güzel değil - yaklaşık 30k tahmini bir alt ağaç maliyeti ile bu çok iş. (Farenizi PasteThePlan'da seçme operatörünün üzerine getirerek görebilirsiniz.) Peki sadece 100-200 satırlarını istiyorsak ne olur? Bu sözdizimini SQL Server 2012 ve sonrasında kullanabiliriz:

SELECT * FROM dbo.Users ORDER BY DisplayName OFFSET 100 ROWS FETCH NEXT 100 ROWS ONLY;

Bununla ilgili yürütme planı da oldukça çirkin:

Bir sıralama ve bir üst ile kümelenmiş dizin taraması

SQL Server, sıralı listeyi oluşturmak için hala tüm tabloyu tarar ve size 100-200 satırlarınızı verir ve maliyet hala 30k civarındadır. Daha da kötüsü, bu tüm liste sorgunuz her çalıştırıldığında yeniden oluşturulacaktır (çünkü sonuçta birisi DisplayName'ini değiştirmiş olabilir.)

Daha hızlı gitmek için, tablonuzun bir kopyası olan DisplayName'de bu alana göre sıralanmış kümelenmemiş bir dizin oluşturabiliriz:

CREATE INDEX IX_DisplayName ON dbo.Users(DisplayName);

Bu dizinle, sorgumuzun yürütme planı artık bir dizin arıyor:

Dizin arama ve anahtar arama

Sorgu anında tamamlanır ve tahmini alt ağaç maliyeti yalnızca 0,66'dır (30k yerine).

Özetle, verileri sık sık çalıştırdığınız sorguları destekleyecek şekilde düzenlerseniz, evet, SQL Server sorgularınızı daha hızlı hale getirmek için kısayollar alabilir. Öte yandan, tüm sahip olduğunuz yığınlar veya kümelenmiş dizinler varsa, mahvoldunuz.


"Varsayılan olarak, DisplayName alanında dizin yoktur, bu nedenle SQL Server tüm tabloyu taramalı ve sonra DisplayName'e göre sıralamalıdır." Bu çok temel bir soru ise sorun: Cevabınızdan alıntı yaptığımda, "Tüm tabloyu tara" ifadesi, tüm verilerin belleğe getirilmesi ve sıralanması (doğru yol gibi görünmemesi) anlamına mı geliyor?
AV94

Cevabınızdan, alan indekslenmişse, SQL gibi indeks (B-ağacı vb.) Ararken ve doğrudan bu noktaya (100. satır) giderken 100. ila 200. satır gibi sorgular yapmanın çok verimli olduğunu anlıyorum. Bunun doğru bir anlayış olup olmadığını söyleyebilir misiniz?
AV94

@AnilVedala ilk sorunuz hakkında - evet, verilerin sıralanması gerekiyor. Bir veritabanı bunu sıralanmamış bir listeyle nasıl başarabilir?
Brent Ozar

1
@AnilVedala ikinci sorunuz hakkında - size verdiğim son yürütme planının geldiği yer burası. (Bir yürütme planını nasıl okuyacağınızı soruyorsanız, Grant Fritchey'in Yürütme Planları kitabını alın.)
Brent

15

Tıpkı bir türden kaçınmak için kapaksız bir dizin kullanırken Brent'in cevabına ek olarak, aşağıda çalıştırıldığı görülebilecek daha sonraki sayfa numaralarında potansiyel bir sorun var

SELECT * 
FROM dbo.Users 
ORDER BY DisplayName 
OFFSET 100000 ROWS 
FETCH NEXT 100 ROWS ONLY;

Yürütme planı, 100 satır hariç tümü TOP operatörü tarafından filtrelenmesine rağmen, aramanın 100.100 kez yürütüldüğünü gösterir.

resim açıklamasını buraya girin

Bu, aşağıdaki desen kullanılarak hafifletilebilir

WITH T
     AS (SELECT Id,
                DisplayName
         FROM   dbo.Users
         ORDER  BY DisplayName
        OFFSET 100000 ROWS 
        FETCH NEXT 100 ROWS ONLY
        )
SELECT U.*
FROM   dbo.Users U
       JOIN T
         ON U.Id = T.Id
ORDER  BY T.DisplayName 

Bu , büyük ofset değerleri için hız üzerinde önemli bir etkisi olabilecek aramaları yapmadan önce son 100 satır dışındaki her şeyi filtreler .

resim açıklamasını buraya girin


3

Gerçekten, sorgunuzdaki sayfalandırmayı nasıl uyguladığınıza, verilerin doğasına ve sisteminizin yapılandırılma şekline bağlıdır. SQL Server'ın verilerinizi mümkün olan en az çaba harcadığını kullanarak döndürmeye çalışacağını söylemek oldukça güvenlidir. Açık sıralama düzeni, filtreleme, gruplama veya herhangi bir pencereniz yoksa SQL Server, sorgu planını, yalnızca sorgunuzun gerektirdiği verileri içeren diskteki sayfaları veya daha da iyisi doğrudan arabellek havuzu. Sorguyu sıralama, gruplama, pencereleme ve filtreleme içerecek şekilde değiştirmeye başlar başlamaz karmaşık olmaya başlar.

SQL Performansına çok iyi bir makale var burada onlar sorgu planını nasıl etkilediğini çeşitli şekilde sayfa numarası yöntem ve bazı ayrıntılı anlatır. Çok okumak ve daha sonra onlar işaret ve kendi sisteminizde hangi sorgu planı seçili görmek çeşitli yöntemler denemek tavsiye ediyoruz.

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.