Denali dizilerinin neden kimlik sütunlarından daha iyi performans gösterdiği farz ediliyor?


36

Hangisinin daha iyi olduğuna cevabında : kimlik sütunları mı, yoksa benzersiz id değerleri mi üretildi? mrdenny diyor ki:

SQL Denali çıktığında, kimlikten daha verimli olacak dizileri destekleyecektir, ancak kendinizden daha verimli bir şey yaratamazsınız.

Çok emin değilim. Oracle'ın dizilerini bilerek , ekleme için bir tetikleyici oluşturmalı, her eki saklı bir yordam çağrısı içine yerleştirmeli ya da geçici bir ekleme yaptığımda sırayı doğru kullanmayı unutmamam için dua etmeliyim.

Dizilerin avantajlarının çok açık olduğundan şüpheliyim.


2
Sorunuzu yanıtlamadığını biliyorum, ancak performans farklılıklarından başka, dizilerin başka avantajları da var. Örneğin, bir dizi, IDENTITY için oldukça elverişsiz bir sınırlama olan hedef sütunu güncellemenizi durdurmaz.
nvogel

Yanıtlar:


37

Ben de burada cevaplayacağım. Nasıl IDENTITYve SEQUENCEçalışmanın içindekilerle ilgisi var .

İle IDENTITYSQL Server böylece belleğe değerleri-önbelleğe önceden, bunlar da hazır olduğunu. Ayrıntılar için Martin Smith'in cevabına bakınız. Değerler kullanıldığında, bir arka plan işlemi daha fazla değer üretir. Tahmin edebileceğiniz gibi bu havuz oldukça hızlı bir şekilde tükenebilir, bu da uygulamayı değerleri üreten arkaplan işleminin insafına bırakır.

İle SEQUENCESQL Server önbellek ne kadar büyük olabileceği tanımlamanızı sağlar. SQL Server aslında değerleri önbellekte tutmazken, yalnızca geçerli değeri ve en üstteki değeri korur, bu da değerler oluşturmak için gereken IO miktarını büyük ölçüde azaltır.

Önbelleği çok yükseğe ayarlamayın, bu kullanılabilecek sayıların sayısını azaltacaktır: eğer SQL Server çökerse, kullanılmayan önbellek aralığında belirtilen değerler kaybedilir.

Satır eklemeye gelince, sütun için yalnızca varsayılan bir değer belirtin, şöyle:

DEFAULT (NEXT VALUE FOR Audit.EventCounter),

21

Yana Itzik Ben Gan makale 10 kodlanmış önbellek boyutunu yazılmıştır için IDENTITYdeğiştirilmiş görünüyor. Gönderen bu bağlantı öğesi yapılan yorumlar

Ön tahsisatın boyutu, kimlik özelliğinin tanımlandığı sütunun veri türünün boyutuna dayanmaktadır. Bir SQL Server tamsayı sütunu için, sunucu kimlikleri 1000 değer aralığında önceden tahsis eder. Bigint veri tipi için, sunucu 10000 değer aralığında önceden tahsis eder.

T-SQL Sorgulama kitabı aşağıdaki tablo içeren ancak bu değerler belgelenmiş veya değişmemiş olması garanti olmadığını vurgular.

+-----------------+-----------+
|    DataType     | CacheSize |
+-----------------+-----------+
| TinyInt         | 10        |
| SmallInt        | 100       |
| Int             | 1,000     |
| BigInt, Numeric | 10,000    |
+-----------------+-----------+

Buradaki makale çeşitli önbellek boyutlarını test eder ve parti boyutlarını ekler ve aşağıdaki sonuçları bulur.

görüntü tanımını buraya girin

Büyük kesici uçlar IDENTITYiçin performans gösterdiği anlaşılıyor SEQUENCE. Ancak, önbellek boyutunu 1.000 test etmez ve ayrıca bu sonuçlar sadece bir testtir. Çeşitli yığın boyutlarında uçlarla birlikte özellikle 1000 önbellek boyutuna baktığımda şu sonuçları aldım (her parti büyüklüğünü 50 kez denemek ve sonuçları her zaman μs altında olduğu gibi birleştirmek).

+------------+-----------+-----------+-----------+-----------+-----------+-----------+
|            |             Sequence              |             Identity              |
| Batch Size |    Min    |    Max    |    Avg    |    Min    |    Max    |    Avg    |
+------------+-----------+-----------+-----------+-----------+-----------+-----------+
| 10         | 2,994     | 7,004     | 4,002     | 3,001     | 7,005     | 4,022     |
| 100        | 3,997     | 5,005     | 4,218     | 4,001     | 5,010     | 4,238     |
| 1,000      | 6,001     | 19,013    | 7,221     | 5,982     | 8,006     | 6,709     |
| 10,000     | 26,999    | 33,022    | 28,645    | 24,015    | 34,022    | 26,114    |
| 100,000    | 189,126   | 293,340   | 205,968   | 165,109   | 234,156   | 173,391   |
| 1,000,000  | 2,208,952 | 2,344,689 | 2,269,297 | 2,058,377 | 2,191,465 | 2,098,552 |
+------------+-----------+-----------+-----------+-----------+-----------+-----------+

Daha büyük parti boyutları için IDENTITYsürüm genellikle daha hızlı görünür .

TSQL Sorgu kitabı ayrıca neden IDENTITYsıralamaya göre performans avantajı sağlayabileceğini de açıklıyor .

IDENTITYMasa özeldir ve SEQUENCEdeğildir. Eğer felaket, log arabelleği temizlenmeden önce orta girişte grevde kalacaksa, kurtarma işlemi de insert'i geri alacağından, kurtarılan kimliğin daha erken olması önemli değildir, bu nedenle SQL Server günlük arabelleğini her kimliğe silmeye zorlamaz önbellekle ilgili disk yaz. Ancak Dizi için bu bir veritabanı dışında da dahil olmak üzere - değeri herhangi bir amaç için kullanılabilecek şekilde uygulanır. Yani yukarıdaki örnekte bir milyon eke ve 1000 önbellek büyüklüğüne sahip olan bu, bin günlük basamağa ek bir işlemdir.

Çoğaltılacak komut dosyası

DECLARE @Results TABLE(
  BatchCounter INT,
  NumRows      INT,
  SequenceTime BIGINT,
  IdTime       BIGINT);

DECLARE @NumRows      INT = 10,
        @BatchCounter INT;

WHILE @NumRows <= 1000000
  BEGIN
      SET @BatchCounter = 0;

      WHILE @BatchCounter <= 50
        BEGIN
            --Do inserts using Sequence
            DECLARE @SequenceTimeStart DATETIME2(7) = SYSUTCDATETIME();

            INSERT INTO dbo.t1_Seq1_cache_1000
                        (c1)
            SELECT N
            FROM   [dbo].[TallyTable] (@NumRows)
            OPTION (RECOMPILE);

            DECLARE @SequenceTimeEnd DATETIME2(7) = SYSUTCDATETIME();
            --Do inserts using IDENTITY
            DECLARE @IdTimeStart DATETIME2(7) = SYSUTCDATETIME();

            INSERT INTO dbo.t1_identity
                        (c1)
            SELECT N
            FROM   [dbo].[TallyTable] (@NumRows)
            OPTION (RECOMPILE);

            DECLARE @IdTimeEnd DATETIME2(7) = SYSUTCDATETIME();

            INSERT INTO @Results
            SELECT @BatchCounter,
                   @NumRows,
                   DATEDIFF(MICROSECOND, @SequenceTimeStart, @SequenceTimeEnd) AS SequenceTime,
                   DATEDIFF(MICROSECOND, @IdTimeStart, @IdTimeEnd)             AS IdTime;

            TRUNCATE TABLE dbo.t1_identity;

            TRUNCATE TABLE dbo.t1_Seq1_cache_1000;

            SET @BatchCounter +=1;
        END

      SET @NumRows *= 10;
  END

SELECT NumRows,
       MIN(SequenceTime) AS MinSequenceTime,
       MAX(SequenceTime) AS MaxSequenceTime,
       AVG(SequenceTime) AS AvgSequenceTime,
       MIN(IdTime)       AS MinIdentityTime,
       MAX(IdTime)       AS MaxIdentityTime,
       AVG(IdTime)       AS AvgIdentityTime
FROM   @Results
GROUP  BY NumRows;
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.