Sql sunucusunda tablo değişkenine karşı geçici tabloyu ne zaman kullanmalıyım?


299

Tablo değişkeninde daha fazla ayrıntı öğreniyorum. Geçici tabloların her zaman diskte ve tablo değişkenlerinin bellekte olduğunu, yani tablo değişkeninin temp tablosundan daha az IO işlemi kullandığından, tablo değişkeninin performansının temp tablosundan daha iyi olduğunu söyler.

Ancak bazen, bir tablo değişkeninde bellekte bulunamayan çok fazla kayıt varsa, tablo değişkeni geçici tablo gibi diske yerleştirilir.

Ama "çok fazla kayıt" ın ne olduğunu bilmiyorum. 100.000 kayıt mı? 1000.000 kayıt mı? Kullandığım bir tablo değişkeninin bellekte mi yoksa diskte mi olduğunu nasıl anlayabilirim? SQL Server 2005'te tablo değişkeninin ölçeğini ölçmek veya tablo değişkeni bellekten diske yerleştirildiğinde bana bildirmek için herhangi bir işlev veya araç var mı?


5
Bir tablo değişkeni neredeyse her zaman içindedir tempDB- "bellekte" bir efsanedir. Ayrıca: tablo değişkenleri her zaman sorgu iyileştirici tarafından tam olarak bir satır tutacaktır - çok daha fazlasına sahipseniz, bu durum çok kötü yürütme planlarına yol açabilir.
marc_s


2
@marc_s - Bu ifadede "neredeyse" ifadesini bırakabilirsiniz. Her zaman içeride tempdb(ancak tamamen bellekte de olabilir)
Martin Smith

2
SQL 2014 ile artık bellekte bir tablo değişkeni oluşturabilirsiniz
paparazzo

Yanıtlar:


362

Sorunuz, tablo değişkenlerini ve geçici tabloları çevreleyen bazı yaygın yanılgılara yenildiğinizi gösteriyor.

İki nesne türü arasındaki farklara bakarak DBA sitesinde oldukça kapsamlı bir cevap yazdım . Bu aynı zamanda disk vs bellek hakkında sorunuzu ele alıyor (ikisi arasında davranışta önemli bir fark görmedim).

Başlıktaki soru ile ilgili olarak, bir tablo değişkeninin yerel bir geçici tabloya karşı ne zaman kullanılacağı konusunda her zaman bir seçeneğiniz yoktur. Örneğin işlevlerde, bir tablo değişkeni kullanmak mümkündür ve tabloya bir alt kapsamda yazmanız gerekirse, yalnızca bir #temptablo yapılır (tablo değerli parametreler salt okunur erişime izin verir ).

Bir seçeneğiniz olduğunda, bazı öneriler aşağıdadır (en güvenilir yöntem her ikisini de belirli iş yükünüzle test etmektir).

  1. Bir tablo değişkeninde oluşturulamayan bir dizine ihtiyacınız varsa, elbette bir #temporarytabloya ihtiyacınız olacaktır . Ancak bunun ayrıntıları sürüme bağlıdır. SQL Server 2012 ve altı için yalnızca tablo değişkenleri üzerinde oluşturulabilecek dizinler dolaylı olarak bir UNIQUEveya PRIMARY KEYkısıtlamasıyla oluşturulmuş dizinlerdir . SQL Server 2014, mevcut seçeneklerin bir alt kümesi için satır içi dizin sözdizimini tanıttı CREATE INDEX. Bu, filtrelenmiş dizin koşullarına izin verdiği için genişletildi. INCLUDEBununla birlikte , -d sütunları veya sütun deposu dizinleri içeren dizinler hala tablo değişkenlerinde oluşturulamaz.

  2. Tabloya tekrar tekrar çok sayıda satır ekleyip silecekseniz bir #temporarytablo kullanın . Bu destekler TRUNCATE( DELETEbüyük tablolardan daha etkilidir ) ve a'yı takip eden ek kesici uçlar , burada gösterilen a'yıTRUNCATE izleyenlerden daha iyi performans DELETE gösterebilir .

  3. Çok sayıda satırı silecekseniz veya güncelleyecekseniz, geçici tablo bir tablo değişkeninden çok daha iyi performans gösterebilir - satır kümesi paylaşımını kullanabiliyorsa (örnek için aşağıdaki "Satır kümesi paylaşımının etkileri" konusuna bakın).
  4. Tabloyu kullanarak en uygun plan verilere bağlı olarak değişecekse, tablo kullanın #temporary. Bu, planın verilere göre dinamik olarak yeniden derlenmesini sağlayan istatistiklerin oluşturulmasını destekler (saklı yordamlardaki önbelleğe alınmış geçici tablolar için yeniden derleme davranışının ayrı olarak anlaşılması gerekir).
  5. Tabloyu kullanarak sorgu için en uygun planın değişmesi olası değilse, istatistik oluşturma ve yeniden derleme yükünü atlamak için bir tablo değişkenini düşünebilirsiniz (muhtemelen istediğiniz planı düzeltmek için ipuçları gerekebilir).
  6. Tabloya eklenen verilerin kaynağı potansiyel olarak pahalı bir SELECTifadeden geliyorsa, bir tablo değişkeni kullanmanın bunun paralel bir plan kullanarak bunun olasılığını engelleyeceğini düşünün.
  7. Bir dış kullanıcı işleminin geri alınması için tablodaki verilere ihtiyacınız varsa bir tablo değişkeni kullanın. Bunun olası bir kullanım durumu, uzun adımların ilerlemesini uzun bir SQL toplu işleminde günlüğe kaydetme olabilir.
  8. Bir #tempkullanıcı içinde bir tablo kullanıldığında, işlem kilitleri tablo değişkenlerinden daha uzun süre tutulabilir (işlemin sonuna kadar, ifadenin sonuna kadar kilit türüne ve yalıtım düzeyine bağlı olarak) ve ayrıca tempdbişlem günlüğünün kesilmesini önleyebilir kullanıcı işlemi sona erer. Yani bu tablo değişkenlerinin kullanılmasını destekleyebilir.
  9. Depolanan rutinler içinde hem tablo değişkenleri hem de geçici tablolar önbelleğe alınabilir. Önbelleğe alınan tablo değişkenleri için meta veri bakımı #temporarytablolardan daha azdır . Bob Ward tempdbsunumunda bunun yüksek eşzamanlılık koşullarında sistem tablolarında ek tartışmaya neden olabileceğine dikkat çekiyor . Ek olarak, az miktarda veriyle uğraşırken, bu durum performansta ölçülebilir bir fark yaratabilir .

Satır kümesi paylaşımının etkileri

DECLARE @T TABLE(id INT PRIMARY KEY, Flag BIT);

CREATE TABLE #T (id INT PRIMARY KEY, Flag BIT);

INSERT INTO @T 
output inserted.* into #T
SELECT TOP 1000000 ROW_NUMBER() OVER (ORDER BY @@SPID), 0
FROM master..spt_values v1, master..spt_values v2

SET STATISTICS TIME ON

/*CPU time = 7016 ms,  elapsed time = 7860 ms.*/
UPDATE @T SET Flag=1;

/*CPU time = 6234 ms,  elapsed time = 7236 ms.*/
DELETE FROM @T

/* CPU time = 828 ms,  elapsed time = 1120 ms.*/
UPDATE #T SET Flag=1;

/*CPU time = 672 ms,  elapsed time = 980 ms.*/
DELETE FROM #T

DROP TABLE #T

2
Merhaba Bay Martin Smith. Mi durumda ben sadece Mağaza prosedürü içinde başka sorguda kullanmak için Ids değerleri kümesi saklamak istiyorum. Peki bana ne öneriyorsun?
Jeancarlo Fontalvo

@JeancarloFontalvo - birincil anahtarı açık idve kullanımı olan bir tablo değişkeni OPTION (RECOMPILE)muhtemelen bunun için iyi olur - ancak her ikisini de test edin.
Martin Smith

geçici tablo hem geçici tablo hem de değişken için aynı mıdır?
Syed Aqeel Ashiq

@Syed. Genellikle TV için daha az. Bir kullanıcı işlemi içindeyse kilitler daha önce serbest bırakılabilir. Ayrıca Bob Ward bağlantısına bakınız.
Martin Smith

73

Çok az miktarda veri için (binlerce bayt) bir tablo değişkeni kullanın

Çok fazla veri için geçici bir tablo kullanın

Bunu düşünmenin başka bir yolu: Eğer bir dizinden, otomatik istatistiklerden veya herhangi bir SQL optimizer iyiliğinden yararlanabileceğinizi düşünüyorsanız, veri kümeniz muhtemelen bir tablo değişkeni için çok büyüktür.

Örneğimde, kalıcı bir tabloyu UPDATE / INSERT için kullanmadan önce bir biçime yaklaşık 20 satır koymak ve bunları bir grup olarak değiştirmek istedim. Yani bir tablo değişkeni mükemmel.

Ama aynı zamanda binlerce satırı bir seferde doldurmak için SQL çalıştırıyorum ve geçici tabloların tablo değişkenlerinden çok daha iyi performans gösterdiğini kesinlikle söyleyebilirim .

Bu, CTE'lerin benzer boyutta bir nedenden nasıl endişe duyduklarından farklı değildir - CTE'deki veriler çok küçükse, bir CTE'nin optimize edicinin ortaya çıkardığı kadar iyi veya daha iyi performans gösterdiğini görüyorum, ancak oldukça büyükse seni acıtıyor.

Anlayışım çoğunlukla çok daha fazla ayrıntıya sahip olan http://www.developerfusion.com/article/84397/table-variables-v-temporary-tables-in-sql-server/ adresine dayanıyor .


Paket servisi olan restoran tablo değişkeni küçük veri kümesi için iyidir, ancak daha büyük veri kümesi için geçici tablo kullanın. Binlerce satır içeren bir sorgu var. Tablo değişkeninden geçici tabloya geçerek, sorgu süresi 40 saniyeden 5 saniyeye düşer ve her şey eşit olur.
liang

42

Microsoft burada diyor

Tablo değişkenlerinin dağıtım istatistikleri yoktur, yeniden derlemeleri tetiklemezler. Bu nedenle, birçok durumda, eniyileyici tablo değişkeninin satır içermediği varsayımı üzerine bir sorgu planı oluşturur. Bu nedenle, daha fazla sayıda satır (100'den büyük) bekliyorsanız, tablo değişkeni kullanma konusunda dikkatli olmalısınız. Bu durumda sıcaklık tabloları daha iyi bir çözüm olabilir.


14

Abaküs ile tamamen katılıyorum (üzgünüm - yorum yapmak için yeterli puanınız yok).

Ayrıca, kaç kayıt bulunduğuna değil, kayıtlarınızın boyutuna düştüğünü unutmayın.

Örneğin, her biri 50 sütun içeren 1.000 kayıt ile her biri yalnızca 5 sütun içeren 100.000 kayıt arasındaki performans farkını düşündünüz mü?

Son olarak, belki de ihtiyacınız olandan daha fazla veri sorguluyor / saklıyorsunuz? İşte SQL optimizasyon stratejileri hakkında iyi bir okuma . Özellikle hepsini kullanmıyorsanız, çektiğiniz veri miktarını sınırlayın (bazı SQL programcıları tembelleşir ve sadece küçük bir alt küme kullansalar bile her şeyi seçerler). Unutmayın, SQL sorgu analizörü de en iyi arkadaşınız olabilir.


4

Değişken tablo yalnızca geçerli oturum için kullanılabilir, örneğin, geçerli oturum EXECiçinde başka bir saklı yordam gerekiyorsa , tabloyu geçmek zorunda kalacaksınız Table Valued Parameterve elbette bu performansı etkileyecektir, geçici tablolarla bunu yalnızca geçici tablo adını iletme

Geçici bir tabloyu test etmek için:

  • Açık yönetim stüdyosu sorgu düzenleyicisi
  • Geçici tablo oluşturma
  • Başka bir sorgu düzenleyici penceresi açın
  • Bu tablodan "Kullanılabilir" i seçin

Değişken tablosunu test etmek için:

  • Açık yönetim stüdyosu sorgu düzenleyicisi
  • Değişken tablosu oluşturma
  • Başka bir sorgu düzenleyici penceresi açın
  • Bu tablodan "Kullanılamaz" ı seçin

yaşadığım başka bir şey şudur: Şemanızın GRANTtablo oluşturma ayrıcalığı yoksa, değişken tabloları kullanın.


3

beyan edilen tablolara veri yazarken declare @tbve diğer tablolarla birleştikten sonra, geçici tablolara kıyasla yanıt süresinin tempdb .. # tbçok daha yüksek olduğunu fark ettim .

@ Tb ile onlara katıldığımda , sonucu döndürmenin zamanı çok daha uzun, # tm'den farklı olarak, dönüş neredeyse anlık.

10.000 satırlık ve diğer 5 tabloya katılan testler yaptım


Bu rakamları almak için koştuğunuz testi gönderebilir misiniz?
Dan Def
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.