Disk belleği SQL Server'da ROW_NUMBER ile nasıl çalışır?


13

EmployeeBir milyon kaydı olan bir masam var. Bir web uygulamasında veri disk belleği için aşağıdaki SQL var. İyi çalışıyor. Ancak ben bir sorun olarak gördüğüm - türetilmiş tablo ( değerleri oluşturmak için ) tablodaki tblEmployeetüm kayıtları seçer .EmployeeMyRowNumber

Sanırım, bu Employeetablodaki tüm kayıtların seçilmesine neden oluyor .

Gerçekten çalışıyor mu? Yoksa SQL Server yalnızca özgün Employeetablodan yalnızca 5 kayıt seçmek için optimize edilmiş mi?

DECLARE @Index INT;
DECLARE @PageSize INT;

SET @Index = 3;
SET @PageSize = 5;

SELECT *  FROM
  (SELECT  ROW_NUMBER() OVER (ORDER BY EmpID asc) as MyRowNumber,*
  FROM Employee) tblEmployee
WHERE MyRowNumber BETWEEN ( ((@Index - 1) * @PageSize )+ 1) AND @Index*@PageSize 

Yanıtlar:


17

Teste bir alternatif olabilir:

;WITH x AS (SELECT EmpID, k = ROW_NUMBER() OVER (ORDER BY EmpID) FROM dbo.Emp)
SELECT e.columns
FROM x INNER JOIN dbo.Emp AS e
ON x.EmpID = e.EmpID
WHERE x.k BETWEEN (((@Index - 1) * @PageSize) + 1) AND @Index * @PageSize
ORDER BY ...;

Evet, masaya iki kez vurdunuz, ancak tüm masayı taradığınız CTE'de TÜM verileri değil, sadece anahtarı alıyorsunuz. Ama gerçekten bu makaleye bakmalısınız:

http://www.sqlservercentral.com/articles/T-SQL/66030/

Ve takip tartışması:

http://www.sqlservercentral.com/Forums/Topic672980-329-1.aspx

SQL Server 2012'de elbette yeni OFFSET/ FETCH NEXTsözdizimini kullanabilirsiniz:

;WITH x AS 
(
  SELECT EmpID FROM dbo.Emp
    ORDER BY EmpID
    OFFSET  @PageSize * (@Index - 1) ROWS
    FETCH NEXT @PageSize ROWS ONLY
)
SELECT e.columns
FROM x INNER JOIN dbo.Emp AS e
ON x.EmpID = e.EmpID
ORDER BY ...; 

Ancak OFFSET / FETCH NEXT'in CTE yöntemine göre herhangi bir performans avantajı sunmadığına dikkat edilmelidir
Akash

2
@Akash bunu iyice test ettin mi? Bazı plan farklılıkları gözlemledim, ancak performans hakkında hiçbir şeyden bahsetmedim çünkü kapsamlı bir test yapmadım. Performans aynı olsa bile, sözdizimi biraz daha az kullanışlıdır. Burada bu konuda blog yazdım
Aaron Bertrand

1
Ah, haklısın, bir performans farkı var. Bunu okumuştum: blogs.technet.com/b/dataplatforminsider/archive/2011/11/01/… burada hiçbir farktan bahsetmedi, ancak sadece kanal gösterdiği kanal9.msdn.com/posts/SQL11UPD03-REC-02'yi gördü. bir çok fark .. (ses yetersizliğinde performans farkı olsa da)
Akash

2

Arkasındaki mekanizmayı bilmeseniz de, sorgunuzun performansını şununla karşılaştırarak bunu kendiniz test edebilirsiniz: Çalışan'dan select *.

SQL Server'ın daha yeni sürümleri optimize etmek için oldukça iyi bir iş çıkarır, ancak birkaç faktöre bağlı olabilir.

ROW_NUMBER işlevinizin nasıl performans gösterdiği Order By yan tümcesi tarafından yönlendirilecektir. Örneğinizde, çoğu EmpID'nin birincil anahtar olduğunu tahmin eder.

Bazı vardır kadar karmaşık ve / veya kötü kodlanmış veya dizine tutulan hükümler, sadece bütün veri kümesini (Çok nadir ve sabitlenebilir) dönen daha iyi olabilir. BETWEEN kullanımı ile ilgili sorunlar var.

Tüm satırları uygulamanıza döndürmenin ve çözmesine izin vermenin daha iyi olacağını varsaymadan önce, sorgunuzu optimize etmeye çalışmalısınız. Tahminleri kontrol edin. Sorgu Analizörüne sorun. Bazı alternatifleri test edin.


2

Sorunun row_number () ile ilgili olduğunu biliyorum ama sql server 2012 yeni bir özellik eklemek istiyorum. Sql server 2012 yeni özellik OFSET Fetch sonraki tanıtıldı ve row_number () çok hızlı. Ben kullandım ve bana iyi bir sonuç verir umarım siz de aynı deneyimi doldurursunuz.

Http://blogfornet.com/2013/06/sql-server-2012-offset-use/ üzerinde bir örnek buldum

yararlıdır. Yeni özellikler uygulamak için de size yardımcı olacağını umuyoruz ....


-2

Orijinal tablodaki tüm satırları döndürmeyi değerlendirdiğini sanmıyorum. SQL sunucusu optimize eder. Aksi takdirde bir milyon giriş seçmek çok zaman alacaktır. Şu anda bunu kullanıyorum ve tüm satırları seçmekten çok daha hızlı. Yani, kesinlikle tüm satırları almaz. Bununla birlikte, muhtemelen sipariş sırasında harcanan zaman nedeniyle ilk beş satırı almaktan daha yavaştır


-2
DECLARE @PageIndex int;
DECLARE @PageSize int;
SET @PageIndex = 4;
SET @PageSize = 5;
;With ranked AS   --- Or you can make it a view
(
   SELECT ROW_NUMBER() OVER(ORDER BY IdentityId) AS RowNum,  *
   FROM logeventnew
)
SELECT *   --Your fields here
FROM Ranked
WHERE RowNum BETWEEN ((@PageIndex - 1) * @PageSize + 1)
    AND (@PageIndex * @PageSize)
ORDER BY IdentityId

4
Cevabınızı genişletebilir misiniz? Soru, disk belleği için SQL Server'da nasıl çalıştığı ile ilgilidir - yani veritabanı motoru isteği yerine getirmek için ne yapar. Ne yazık ki, şu andan itibaren cevabınız asıl endişeyi gidermiyor.
Mr.Brownstone
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.