Neden bir tablo değişkenini bu özel durumda #temp tablosunun iki katından daha hızlı kullanıyorsunuz?


37

Buradaki makalede Geçici Tablolar ve Tablo Değişkenleri ile SQL Server Performansı ve SQL Server 2008 Üzerindeki Etkileri, 2005 yılı için gösterilenlere benzer sonuçlar üretebildi.

Saklı yordamları (aşağıdaki tanımlamalar) yalnızca 10 satır ile yürütürken, tablo değişken sürümü geçici tablo sürümünü iki kereden fazla gerçekleştirir.

Prosedür önbelleğini temizledim ve her iki saklı işlemi de 10.000 kez yürüttüm, sonra işlemi 4 kez daha tekrarladım. Aşağıdaki sonuçlar (parti başına ms cinsinden süre)

T2_Time     V2_Time
----------- -----------
8578        2718      
6641        2781    
6469        2813   
6766        2797
6156        2719

Sorum şu: Tablo değişken versiyonunun daha iyi performans göstermesinin nedeni nedir?

Biraz araştırma yaptım. Örneğin: performans sayaçlarına bakmak

SELECT cntr_value
from sys.dm_os_performance_counters
where counter_name = 'Temp Tables Creation Rate';

Her iki durumda da geçici nesnelerin her çalıştırma için yeniden sıfırdan yaratılmak yerine beklenildiği gibi ilk çalıştırmadan sonra önbelleğe alındığını onaylar .

Benzer şekilde izleme Auto Stats, SP:Recompile, SQL:StmtRecompilebu olaylar sadece (ilk çağırma kez gerçekleştiğini gösterir Profiler'da olaylar (aşağıdaki ekran) #tempmasa saklı yordam) ve diğer 9.999 infazlar bu olayların herhangi yükseltmeyin. (Tablo değişkeni sürümü bu olaylardan hiçbirini alamaz)

iz

Saklı yordamın ilk çalıştırmasının biraz daha fazla ek yükü, büyük toplam farkı hesaba katamaz, ancak işlem önbelleğini temizlemek ve her iki işlemi bir kez çalıştırmak için hala sadece birkaç ms sürdüğünden, istatistiklere ya da istatistiklere inanmam. yeniden derler nedeni olabilir.

Gerekli Veritabanı Nesneleri Yaratın

CREATE DATABASE TESTDB_18Feb2012;

GO

USE TESTDB_18Feb2012;

CREATE TABLE NUM 
  ( 
     n INT PRIMARY KEY, 
     s VARCHAR(128) 
  ); 

WITH NUMS(N) 
     AS (SELECT TOP 1000000 ROW_NUMBER() OVER (ORDER BY $/0) 
         FROM   master..spt_values v1, 
                master..spt_values v2) 
INSERT INTO NUM 
SELECT N, 
       'Value: ' + CONVERT(VARCHAR, N) 
FROM   NUMS 

GO

CREATE PROCEDURE [dbo].[T2] @total INT 
AS 
  CREATE TABLE #T 
    ( 
       n INT PRIMARY KEY, 
       s VARCHAR(128) 
    ) 

  INSERT INTO #T 
  SELECT n, 
         s 
  FROM   NUM 
  WHERE  n%100 > 0 
         AND n <= @total 

  DECLARE @res VARCHAR(128) 

  SELECT @res = MAX(s) 
  FROM   NUM 
  WHERE  n <= @total 
         AND NOT EXISTS(SELECT * 
                        FROM   #T 
                        WHERE  #T.n = NUM.n) 
GO

CREATE PROCEDURE [dbo].[V2] @total INT 
AS 
  DECLARE @V TABLE ( 
    n INT PRIMARY KEY, 
    s VARCHAR(128)) 

  INSERT INTO @V 
  SELECT n, 
         s 
  FROM   NUM 
  WHERE  n%100 > 0 
         AND n <= @total 

  DECLARE @res VARCHAR(128) 

  SELECT @res = MAX(s) 
  FROM   NUM 
  WHERE  n <= @total 
         AND NOT EXISTS(SELECT * 
                        FROM   @V V 
                        WHERE  V.n = NUM.n) 


GO

Test Komut Dosyası

SET NOCOUNT ON;

DECLARE @T1 DATETIME2,
        @T2 DATETIME2,
        @T3 DATETIME2,  
        @Counter INT = 0

SET @T1 = SYSDATETIME()

WHILE ( @Counter < 10000)
BEGIN
EXEC dbo.T2 10
SET @Counter += 1
END

SET @T2 = SYSDATETIME()
SET @Counter = 0

WHILE ( @Counter < 10000)
BEGIN
EXEC dbo.V2 10
SET @Counter += 1
END

SET @T3 = SYSDATETIME()

SELECT DATEDIFF(MILLISECOND,@T1,@T2) AS T2_Time,
       DATEDIFF(MILLISECOND,@T2,@T3) AS V2_Time

Profilci izi, istatistiklerin #tempmasaya ancak bir kez daha oluşturulmasına ve ardından 9.999 kez daha doldurulmasına rağmen bir kez oluşturulduğunu gösterir .
Martin Smith

Yanıtlar:


31

Her SET STATISTICS IO ONikisi için de çıktı benzer görünüyor

SET STATISTICS IO ON;
PRINT 'V2'
EXEC dbo.V2 10
PRINT 'T2'
EXEC dbo.T2 10

verir

V2
Table '#58B62A60'. Scan count 0, logical reads 20
Table 'NUM'. Scan count 1, logical reads 3

Table '#58B62A60'. Scan count 10, logical reads 20
Table 'NUM'. Scan count 1, logical reads 3

T2
Table '#T__ ... __00000000E2FE'. Scan count 0, logical reads 20
Table 'NUM'. Scan count 1, logical reads 3

Table '#T__ ... __00000000E2FE'. Scan count 0, logical reads 20
Table 'NUM'. Scan count 1, logical reads 3

Ve Aaron yorumlarda da belirtildiği gibi, tablo değişken sürümü için plan aslında daha az etkilidir, çünkü her ikisi de dbo.NUM, #temptablo sürümünde bir indeks arama tarafından yönlendirilen bir iç içe döngü planına sahipken, tablo değişkeninde [#T].n = [dbo].[NUM].[n]kalan [#T].[n]<=[@total]değişken ile endekse bir arama yapar. sürüm @V.n <= [@total], artık yüklem ile bir dizin araması gerçekleştirir @V.[n]=[dbo].[NUM].[n]ve bu nedenle daha fazla satır işler (bu plan daha fazla satır için bu kadar düşük performans gösteriyor)

Belirli spidlerin bekleme türlerine bakmak için Genişletilmiş Olayları kullanmak , bu sonuçları 10.000 çalıştırma için verir.EXEC dbo.T2 10

+---------------------+------------+----------------+----------------+----------------+
|                     |            |     Total      | Total Resource |  Total Signal  |
| Wait Type           | Wait Count | Wait Time (ms) | Wait Time (ms) | Wait Time (ms) |
+---------------------+------------+----------------+----------------+----------------+
| SOS_SCHEDULER_YIELD | 16         | 19             | 19             | 0              |
| PAGELATCH_SH        | 39998      | 14             | 0              | 14             |
| PAGELATCH_EX        | 1          | 0              | 0              | 0              |
+---------------------+------------+----------------+----------------+----------------+

ve bu sonuçlar 10.000 EXEC dbo.V2 10

+---------------------+------------+----------------+----------------+----------------+
|                     |            |     Total      | Total Resource |  Total Signal  |
| Wait Type           | Wait Count | Wait Time (ms) | Wait Time (ms) | Wait Time (ms) |
+---------------------+------------+----------------+----------------+----------------+
| PAGELATCH_EX        | 2          | 0              | 0              | 0              |
| PAGELATCH_SH        | 1          | 0              | 0              | 0              |
| SOS_SCHEDULER_YIELD | 676        | 0              | 0              | 0              |
+---------------------+------------+----------------+----------------+----------------+

Bu nedenle, masadaki PAGELATCH_SHbekleme sayısının çok daha fazla olduğu açıktır #temp. Genişletti olayları izlemesine bekleme kaynağını eklemenin herhangi bir yolunun farkında değilim.

WHILE 1=1
EXEC dbo.T2 10

Başka bir bağlantıda oylama yaparken sys.dm_os_waiting_tasks

CREATE TABLE #T(resource_description NVARCHAR(2048))

WHILE 1=1
INSERT INTO #T
SELECT resource_description
FROM sys.dm_os_waiting_tasks
WHERE session_id=<spid_of_other_session> and wait_type='PAGELATCH_SH'

Bu koşuyu yaklaşık 15 saniye çalıştırdıktan sonra, aşağıdaki sonuçları topladı.

+-------+----------------------+
| Count | resource_description |
+-------+----------------------+
|  1098 | 2:1:150              |
|  1689 | 2:1:146              |
+-------+----------------------+

Bu sayfaların her ikisi üzerinde (farklı) olmayan kümelenmiş dizinleri aittir kilitli olan tempdb.sys.sysschobjstaban adlı tabloya 'nc1've 'nc2'.

Çalışmalar tempdb.sys.fn_dblogsırasında sorgulama , her saklı prosedürün ilk uygulaması tarafından eklenen log kayıtlarının sayısının bir miktar değişken olduğunu ancak sonraki işlemler için her bir yinelemenin eklediği sayının çok tutarlı ve öngörülebilir olduğunu gösterir. Prosedür planları önbelleğe alındıktan sonra, günlük girişlerinin sayısı #tempsürüm için gerekenlerin yaklaşık yarısı kadardır .

+-----------------+----------------+------------+
|                 | Table Variable | Temp Table |
+-----------------+----------------+------------+
| First Run       |            126 | 72 or 136  |
| Subsequent Runs |             17 | 32         |
+-----------------+----------------+------------+

#tempSP işlem tablosu girişleri için işlem günlüğü girişlerini daha ayrıntılı incelemek, her bir saklı yordamın çağrılmasının ardından üç işlem ve tablo değişkeni yalnızca iki işlem oluşturur.

+---------------------------------+----+---------------------------------+----+
|           #Temp Table                |         @Table Variable              |
+---------------------------------+----+---------------------------------+----+
| CREATE TABLE                    |  9 |                                 |    |
| INSERT                          | 12 | TVQuery                         | 12 |
| FCheckAndCleanupCachedTempTable | 11 | FCheckAndCleanupCachedTempTable |  5 |
+---------------------------------+----+---------------------------------+----+

INSERT/ TVQUERYİşlemler ismi hariç özdeştir. Bu, geçici tabloya veya tablo değişkenine eklenmiş 10 satırın her birinin ve LOP_BEGIN_XACT/ LOP_COMMIT_XACTgirdilerinin günlük kayıtlarını içerir .

CREATE TABLEİşlem yalnızca görünen #Tempsürümü ve aşağıdaki gibi görünüyor.

+-----------------+-------------------+---------------------+
|    Operation    |      Context      |    AllocUnitName    |
+-----------------+-------------------+---------------------+
| LOP_BEGIN_XACT  | LCX_NULL          |                     |
| LOP_SHRINK_NOOP | LCX_NULL          |                     |
| LOP_MODIFY_ROW  | LCX_CLUSTERED     | sys.sysschobjs.clst |
| LOP_DELETE_ROWS | LCX_MARK_AS_GHOST | sys.sysschobjs.nc1  |
| LOP_INSERT_ROWS | LCX_INDEX_LEAF    | sys.sysschobjs.nc1  |
| LOP_DELETE_ROWS | LCX_MARK_AS_GHOST | sys.sysschobjs.nc2  |
| LOP_INSERT_ROWS | LCX_INDEX_LEAF    | sys.sysschobjs.nc2  |
| LOP_MODIFY_ROW  | LCX_CLUSTERED     | sys.sysschobjs.clst |
| LOP_COMMIT_XACT | LCX_NULL          |                     |
+-----------------+-------------------+---------------------+

FCheckAndCleanupCachedTempTableİşlemin hem görünür ancak içinde 6 ek girişler var #tempsürümü. Bunlar atıfta bulunan 6 satırdır sys.sysschobjsve yukarıdakilerle tamamen aynı desene sahiptir.

+-----------------+-------------------+----------------------------------------------+
|    Operation    |      Context      |                AllocUnitName                 |
+-----------------+-------------------+----------------------------------------------+
| LOP_BEGIN_XACT  | LCX_NULL          |                                              |
| LOP_DELETE_ROWS | LCX_NONSYS_SPLIT  | dbo.#7240F239.PK__#T________3BD0199374293AAB |
| LOP_HOBT_DELTA  | LCX_NULL          |                                              |
| LOP_HOBT_DELTA  | LCX_NULL          |                                              |
| LOP_MODIFY_ROW  | LCX_CLUSTERED     | sys.sysschobjs.clst                          |
| LOP_DELETE_ROWS | LCX_MARK_AS_GHOST | sys.sysschobjs.nc1                           |
| LOP_INSERT_ROWS | LCX_INDEX_LEAF    | sys.sysschobjs.nc1                           |
| LOP_DELETE_ROWS | LCX_MARK_AS_GHOST | sys.sysschobjs.nc2                           |
| LOP_INSERT_ROWS | LCX_INDEX_LEAF    | sys.sysschobjs.nc2                           |
| LOP_MODIFY_ROW  | LCX_CLUSTERED     | sys.sysschobjs.clst                          |
| LOP_COMMIT_XACT | LCX_NULL          |                                              |
+-----------------+-------------------+----------------------------------------------+

Her iki işlemde de bu 6 satıra bakıldığında, aynı işlemlere karşılık gelirler. İlki LOP_MODIFY_ROW, LCX_CLUSTERED, içindeki modify_datesütuna yapılan bir güncellemedir sys.objects. Kalan beş satırın tümü nesne yeniden adlandırma ile ilgilidir. Çünkü nameetkilenen her iki NCI'nin ( nc1ve nc2) ana sütunu budur, bu olanlar için bir silme / ekleme olarak gerçekleştirilir, daha sonra kümelenmiş dizine geri döner ve bunu da günceller.

#tempTablo sürümü için, saklı yordamın FCheckAndCleanupCachedTempTableişlem tarafından gerçekleştirilen temizlemenin bir kısmı sona erdiğinde , geçici çizelgenin benzeri #T__________________________________________________________________________________________________________________00000000E316bir şeyden farklı bir iç isme yeniden adlandırıldığı #2F4A0079ve CREATE TABLEişlem girildiği zaman işlemin yeniden adlandırıldığı anlaşılmaktadır. Bu çevirme kayma adı, diğerinde dbo.T2iken bir döngüde yürütülen bir bağlantıda görülebilir.

WHILE 1=1
SELECT name, object_id, create_date, modify_date
FROM tempdb.sys.objects 
WHERE name LIKE '#%'

Örnek Sonuçlar

Ekran görüntüsü

Dolayısıyla, Alex'in ima ettiği gibi gözlenen performans farklılığı için olası bir açıklama, sistem tablolarını bunun içinde tutan bu ek çalışma olduğudur tempdb.


Her iki yordamı bir döngüde çalıştırdığınızda, Visual Studio Code profilcisi aşağıdakileri ortaya çıkarır

+-------------------------------+--------------------+-------+-----------+
|           Function            |    Explanation     | Temp  | Table Var |
+-------------------------------+--------------------+-------+-----------+
| CXStmtDML::XretExecute        | Insert ... Select  | 16.93 | 37.31     |
| CXStmtQuery::ErsqExecuteQuery | Select Max         | 8.77  | 23.19     |
+-------------------------------+--------------------+-------+-----------+
| Total                         |                    | 25.7  | 60.5      |
+-------------------------------+--------------------+-------+-----------+

Tablo değişkeni sürümü, insert ifadesini ve sonraki seçimi yapan sürenin yaklaşık% 60'ını harcar, geçici tablo ise yarısından azdır. Bu, OP'de gösterilen zamanlamalarla aynıdır ve yukarıdaki sonuçla, performanstaki farkın, sorgu çalışmasının kendisinde geçirilen zamandan ötürü değil, yardımcı çalışma yapmak için harcanan zamana göre olduğu sonucuna varılmıştır.

Geçici tablo versiyonunda "eksik"% 75'e katkıda bulunan en önemli fonksiyonlar

+------------------------------------+-------------------+
|              Function              | Inclusive Samples |
+------------------------------------+-------------------+
| CXStmtCreateTableDDL::XretExecute  | 26.26%            |
| CXStmtDDL::FinishNormalImp         | 4.17%             |
| TmpObject::Release                 | 27.77%            |
+------------------------------------+-------------------+
| Total                              | 58.20%            |
+------------------------------------+-------------------+

Hem yarat hem de bırak işlevlerinin altında, işlev CMEDProxyObject::SetName, kapsayıcı bir örnek değeriyle gösterilir 19.6%. Bundan geçici tablodaki zamanın% 39.2'sinin daha önce tarif edilen yeniden isimlendirmeyle alındığı sonucuna vardım.

Tablo değişken versiyonundaki ve% 40’a katkıda bulunanların en büyüğü

+-----------------------------------+-------------------+
|             Function              | Inclusive Samples |
+-----------------------------------+-------------------+
| CTableCreate::LCreate             | 7.41%             |
| TmpObject::Release                | 12.87%            |
+-----------------------------------+-------------------+
| Total                             | 20.28%            |
+-----------------------------------+-------------------+

Geçici Masa Profili

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

Tablo Değişken Profil

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


10

Disko cehennemi

Bu daha eski bir soru olduğundan, aynı performans profilinin hala mevcut olup olmadığını veya özelliklerin değişip değişmediğini görmek için SQL Server'ın daha yeni sürümlerinde konuyu tekrar gözden geçirmeye karar verdim.

Özellikle, SQL Server 2019 için bellek içi sistem tablolarının eklenmesi, yeniden test edilmeye değer bir durum gibi görünmektedir.

Biraz farklı bir test koşum kullanıyorum, çünkü bu konuda başka bir şey üzerinde çalışırken karşılaştım.

Test testleri

Yığın Taşması'nın 2013 sürümünü kullanarak, bu endekse ve şu iki prosedüre sahibim:

Dizin:

CREATE INDEX ix_whatever 
    ON dbo.Posts(OwnerUserId) INCLUDE(Score);
GO

Geçici tablo:

    CREATE OR ALTER PROCEDURE dbo.TempTableTest(@Id INT)
    AS
    BEGIN
    SET NOCOUNT ON;

        CREATE TABLE #t(i INT NOT NULL);
        DECLARE @i INT;

        INSERT #t ( i )
        SELECT p.Score
        FROM dbo.Posts AS p
        WHERE p.OwnerUserId = @Id;

        SELECT @i = AVG(t.i)
        FROM #t AS t;

    END;
    GO 

Tablo değişkeni:

    CREATE OR ALTER PROCEDURE dbo.TableVariableTest(@Id INT)
    AS
    BEGIN
    SET NOCOUNT ON;

        DECLARE @t TABLE (i INT NOT NULL);
        DECLARE @i INT;

        INSERT @t ( i )
        SELECT p.Score
        FROM dbo.Posts AS p
        WHERE p.OwnerUserId = @Id;

        SELECT @i = AVG(t.i)
        FROM @t AS t;

    END;
    GO 

Herhangi bir potansiyel ASYNC_NETWORK_IO beklemesini önlemek için , sarma prosedürleri kullanıyorum.

CREATE PROCEDURE #TT AS
SET NOCOUNT ON;
    DECLARE @i INT = 1;
    DECLARE @StartDate DATETIME2(7) = SYSDATETIME();

    WHILE @i <= 50000
        BEGIN
            EXEC dbo.TempTableTest @Id = @i;
            SET @i += 1;
        END;
    SELECT DATEDIFF(MILLISECOND, @StartDate, SYSDATETIME()) AS [ElapsedTimeMilliseconds];
GO

CREATE PROCEDURE #TV AS
SET NOCOUNT ON;
    DECLARE @i INT = 1;
    DECLARE @StartDate DATETIME2(7) = SYSDATETIME();

    WHILE @i <= 50000
        BEGIN
            EXEC dbo.TableVariableTest @Id = @i;
            SET @i += 1;
        END;
    SELECT DATEDIFF(MILLISECOND, @StartDate, SYSDATETIME()) AS [ElapsedTimeMilliseconds];
GO

SQL Server 2017

2014 ve 2016'dan beri temelde RELICS olduğundan, 2017 ile testime başlıyorum. Ayrıca, kısacası , kodu Perfview ile profillemeye doğru atlıyorum . Gerçek hayatta, beklemeye, mandallara, spinlock'lara, çılgın iz bayraklarına ve diğer şeylere baktım.

Kodu profillemek, ilgilenilen herhangi bir şeyi açığa çıkaran tek şey.

Zaman farkı:

  • Sıcaklık tablosu: 17891 ms
  • Tablo Değişken: 5891 ms

Hala çok açık bir fark, ha? Peki, SQL Server şimdi neyi vuruyor?

FINDIK

Farklı örneklerde ilk iki artışa baktığımızda, en büyük iki suçlu görüyoruz sqlminve görüyoruz sqlsqllang!TCacheStore<CacheClockAlgorithm>::GetNextUserDataInHashBucket.

FINDIK

Çağrı yığınlarındaki isimlere bakılırsa, geçici tabloları temizleme ve dahili olarak yeniden adlandırma, geçici tablo çağrısı ile tablo değişken çağrısı arasındaki en büyük zamandır.

Tablo değişkenleri dahili olarak temp tabloları tarafından desteklense de, bu bir sorun gibi görünmüyor.

SET STATISTICS IO ON;
DECLARE @t TABLE(id INT);
SELECT * FROM @t AS t;

Tablo '# B98CE339'. Tarama sayısı 1

Tablo değişken testi için arama yığınlarına bakmak, ana suçlulardan hiçbirini göstermez:

FINDIK

SQL Server 2019 (Vanilya)

Tamam, bu hala SQL Server 2017'de bir sorun, 2019'da kutudan farklı bir şey var mı?

İlk önce, kolumda hiçbir şey olmadığını göstermek için:

SELECT c.name,
       c.value_in_use,
       c.description
FROM sys.configurations AS c
WHERE c.name = 'tempdb metadata memory-optimized';

FINDIK

Zaman farkı:

  • Sıcaklık tablosu: 15765 ms
  • Tablo Değişken: 7250 ms

Her iki prosedür farklıydı. Temp tablo çağrısı birkaç saniye daha hızlıydı ve tablo değişken çağrısı yaklaşık 1.5 saniye daha yavaştı. Tablo değişkeninin yavaşlaması , 2019'da yeni bir optimize edici seçenek olan tablo değişkeni ertelenmiş derleme ile kısmen açıklanabilir .

Perfview farkına bakıldığında, biraz değişti - sqlmin artık orada değil - ama sqllang!TCacheStore<CacheClockAlgorithm>::GetNextUserDataInHashBucket.

FINDIK

SQL Server 2019 (Bellek İçi Tempdb sistem tabloları)

Peki ya bellek sistemi tablosundaki bu yeni şey? Hımm? Şuna uydunuz mu?

Hadi açalım!

EXEC sys.sp_configure @configname = 'advanced', 
                      @configvalue = 1  
RECONFIGURE;

EXEC sys.sp_configure @configname = 'tempdb metadata memory-optimized', 
                      @configvalue = 1 
RECONFIGURE;

Bunun bir SQL Server'ın yeniden başlatılmasını gerektirdiğini unutmayın, bu yüzden bu güzel Cuma öğleden sonra SQL'i yeniden başlatırken afedersiniz.

Şimdi işler farklı görünüyor:

SELECT c.name,
       c.value_in_use,
       c.description
FROM sys.configurations AS c
WHERE c.name = 'tempdb metadata memory-optimized';

SELECT *, 
       OBJECT_NAME(object_id) AS object_name, 
       @@VERSION AS sql_server_version
FROM tempdb.sys.memory_optimized_tables_internal_attributes;

FINDIK

Zaman farkı:

  • Sıcaklık tablosu: 11638 ms
  • Tablo değişkeni: 7403 ms

Temp tabloları yaklaşık 4 saniye daha iyi yaptı! Bu bir şey.

Ben bir şeyleri severim.

Bu sefer, Perfview fark çok ilginç değil. Yan yana, tahtadaki zamanın ne kadar yakın olduğunu not etmek ilginç:

FINDIK

hkengine!Farkın ilginç noktalarından biri, hekaton-ish özelliklerinin şu anda kullanımda olması nedeniyle açık görülebilen çağrılardır .

FINDIK

Farklılığın en iyi iki maddesi arasında, fazla bir şey yapamam ntoskrnl!?:

FINDIK

Ya da sqltses!CSqlSortManager_80::GetSortKeySmrtr Ppl ™ 'in bakması için buradalar:

FINDIK

Belgelendirilmemiş ve üretim için kesinlikle güvenli olmadığına dikkat edin, bu nedenle lütfen bellek içi özelliğe eklenmiş ek geçici tablo sistem nesnelerine (sysrowsets, sysallocunits ve sysseobjvalues) sahip olmak için kullanabileceğiniz başlangıç ​​izleme bayrağını kullanmayın, ancak bu Bu durumda uygulama sürelerinde gözle görülür bir fark yaratmadı.

Hesabı yuvarlamak

Daha yeni SQL server sürümlerinde bile, tablo değişkenlerine yapılan yüksek frekanslı aramalar, temp tablolarına yapılan yüksek frekanslı aramalardan çok daha hızlıdır.

Derlemeleri, yeniden derlemeleri, otomatik istatistikleri, mandalları, spinlock'ları, önbellekleri veya diğer sorunları suçlamak cazip gelse de, sorun geçici olarak hala masa temizleme işlemini yönetme konusundadır.

SQL Server 2019'da bellek içi sistem tabloları etkin durumdayken daha yakın bir çağrıdır, ancak çağrı sıklığı yüksekken tablo değişkenleri daha iyi performans gösterir.

Tabii ki, bir zamanlar bir vaping adaçayı mused olarak: "plan seçimi bir sorun olmadığı zaman tablo değişkenleri kullanın".


Güzel - üzgünüm, "hata ayıklama" blog yazısındaki bağlantıyı izleyene kadar buna bir cevap eklediğinizi özledim
Martin Smith
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.