Tablo değişkeninde dizin oluşturma


190

SQL Server 2000'de bir tablo değişkeni üzerinde bir dizin oluşturabilir misiniz?

yani

DECLARE @TEMPTABLE TABLE (
     [ID] [int] NOT NULL PRIMARY KEY
    ,[Name] [nvarchar] (255) COLLATE DATABASE_DEFAULT NULL 
)

Tarihinde bir dizin oluşturabilir miyim Name?


3
Her iki tür geçici tablo oluşturmanın bir maliyeti vardır; ve eğer bir indekse ihtiyacınız olacak kadar çok veriye sahipseniz, gerçek bir tablo kullanmaya bakmanın zamanı gelmiş olabilir; işlem için güvenli olacak şekilde ayarladığınızı; spid veya kullanıcı kimliğine göre filtreleyin ve ardından sonunda temizleyin. Gerçek tablolar v geçici tabloların hem iniş çıkışları vardır hem de performans bir sorunsa; gerçek bir tablo ile de deneyin.
u07ch

Bir geçici tablo 'IS' gerçek bir tablo, işiniz bittiğinde ortadan kalkar. Gerçek fark (otomatik olarak ortadan kalkacak dışında) TempDB'de olmasıdır. Dizinler ve kısıtlamalar söz konusu olduğunda bu çok büyüktür, çünkü yalnızca kodunuzun diğer yürütmeleriyle değil, aynı zamanda örneğinizdeki diğer veritabanlarında kod yürütmesiyle de ad çakışmalarıyla sonuçlanabilir.
bielawski

@bielawski bu geçici tablo değil tablo değişkeni. Tablo değişkenleri açıkça adlandırılmış kısıtlamalara izin vermez, sistem tarafından oluşturulan adların benzersiz olduğu garanti edilir. 2014'ten adlandırılmış dizinlere izin veriyorlar, ancak bu bir sorun değil çünkü dizinlerin yalnızca nesneler arasında değil bir nesnenin içinde benzersiz bir şekilde adlandırılması gerekiyor.
Martin Smith

Demek istediğim 2 kat. 1) İşlem karışmasını önlemek için bir değişken kullanmak dışında bir geçici tablo ile tablo değişkeni arasında önemli bir fark yoktur. Ancak V-2000'de bir değişkene kısıtlama, indeks ekleme ... sözdizimi yoktur. 2) yerine, endeksler gibi adlandırılmış tablo uzantıları geçici bir tablo kullanabilirsiniz biri Verilen OLACAK statik adı kullanılırsa aynı SP eşzamanlı yürütülmesi kopyaları ile çatışma! Aşağıdaki mekanizma, bu kesin koşullar altında çakışan adlandırılmış dizinlere SP başarısızlıklarını izlediğim için açıkça geliştirildi. Benzersiz olmalı ZORUNLU.
bielawski

1
@bielawski - Hiçbir dizin adının nesneler arasında benzersiz olması gerekmez - yalnızca kısıtlama adları geçerlidir. bu test etmek önemsizdir. Sadece yürütmekCREATE TABLE #T1(X INT); CREATE TABLE #T2(X INT); CREATE INDEX IX ON #T1(X); CREATE INDEX IX ON #T2(X);
Martin Smith

Yanıtlar:


363

Soru SQL Server 2000 olarak etiketlendi, ancak en son sürümde gelişen insanların yararına ilk önce bunu ele alacağım.

SQL Server 2014

Aşağıda tartışılan kısıtlamaya dayalı dizinler ekleme yöntemlerine ek olarak, SQL Server 2014'te benzersiz olmayan dizinlerin doğrudan tablo değişkeni bildirimlerinde satır içi sözdizimi ile belirtilmesine izin verir.

Bunun için örnek sözdizimi aşağıdadır.

/*SQL Server 2014+ compatible inline index syntax*/
DECLARE @T TABLE (
C1 INT INDEX IX1 CLUSTERED, /*Single column indexes can be declared next to the column*/
C2 INT INDEX IX2 NONCLUSTERED,
       INDEX IX3 NONCLUSTERED(C1,C2) /*Example composite index*/
);

Filtrelenmiş dizinler ve sütunları içeren dizinler şu anda bu sözdizimi ile bildirilemez, ancak SQL Server 2016 bunu biraz daha rahatlatır. CTP 3.1'den artık tablo değişkenleri için filtrelenmiş dizinler bildirmek mümkündür. RTM tarafından o olabilir dahil sütunları da izin verildiğini durum ancak mevcut pozisyon onlar olmasıdır "muhtemel kaynak sıkıntıları nedeniyle SQL16 içine yapmayacağız"

/*SQL Server 2016 allows filtered indexes*/
DECLARE @T TABLE
(
c1 INT NULL INDEX ix UNIQUE WHERE c1 IS NOT NULL /*Unique ignoring nulls*/
)

SQL Server 2000-2012

Ad üzerinde bir dizin oluşturabilir miyim?

Kısa cevap: Evet.

DECLARE @TEMPTABLE TABLE (
  [ID]   [INT] NOT NULL PRIMARY KEY,
  [Name] [NVARCHAR] (255) COLLATE DATABASE_DEFAULT NULL,
  UNIQUE NONCLUSTERED ([Name], [ID]) 
  ) 

Daha ayrıntılı bir cevap aşağıdadır.

SQL Server'daki geleneksel tablolar kümelenmiş bir dizine sahip olabilir veya yığın olarak yapılandırılabilir .

Kümelenmiş dizinler, yinelenen anahtar değerlerine izin vermemek için benzersiz veya varsayılan olmayan benzersiz olarak bildirilebilir. Değil biricik sonra SQL Server sessizce bir eklerse benzersizleştirici herhangi bir yinelenen tuşlara benzersiz yapmak için.

Kümelenmemiş dizinler de açıkça benzersiz olarak bildirilebilir. Aksi takdirde SQL Server , tüm dizin anahtarlarına (yalnızca kopyalar değil) tüm konum anahtarlarına satır bulucuyu (kümelenmiş dizin anahtarı veya yığın için RID ) ekler .

SQL Server 2000 - 2012'de tablo değişkenleri üzerindeki dizinler yalnızca bir UNIQUEveya PRIMARY KEYkısıtlama oluşturularak dolaylı olarak oluşturulabilir . Bu kısıtlama türleri arasındaki fark, birincil anahtarın boş değerli olmayan sütunlarda olması gerektiğidir. Benzersiz bir kısıtlamaya katılan sütunlar boş bırakılabilir. (SQL Server'ın NULLs varlığında benzersiz kısıtlamalar uygulaması SQL Standardında belirtilenlere uygun değildir). Ayrıca bir tablonun yalnızca bir birincil anahtarı olabilir, ancak birden fazla benzersiz kısıtlaması olabilir.

Bu mantıksal kısıtlamaların her ikisi de fiziksel olarak benzersiz bir dizinle uygulanır. Aksi açıkça belirtilmezse PRIMARY KEY, kümelenmiş dizin ve kümelenmemiş benzersiz kısıtlamalar olur, ancak bu davranış sınırlama bildirimi belirtilerek CLUSTEREDveya NONCLUSTEREDaçıkça belirtilerek geçersiz kılınabilir (Örnek sözdizimi)

DECLARE @T TABLE
(
A INT NULL UNIQUE CLUSTERED,
B INT NOT NULL PRIMARY KEY NONCLUSTERED
)

Yukarıdakilerin bir sonucu olarak, SQL Server 2000 - 2012'de tablo değişkenleri üzerinde aşağıdaki dizinler örtük olarak oluşturulabilir.

+-------------------------------------+-------------------------------------+
|             Index Type              | Can be created on a table variable? |
+-------------------------------------+-------------------------------------+
| Unique Clustered Index              | Yes                                 |
| Nonunique Clustered Index           |                                     |
| Unique NCI on a heap                | Yes                                 |
| Non Unique NCI on a heap            |                                     |
| Unique NCI on a clustered index     | Yes                                 |
| Non Unique NCI on a clustered index | Yes                                 |
+-------------------------------------+-------------------------------------+

Sonuncusu biraz açıklama gerektirir. Bu cevabın başlangıcındaki tablo değişkeni tanımında, benzersiz olmayan kümelenmemiş dizin, benzersiz bir dizin Nametarafından simüle edilir (SQL Server'ın kümelenmiş dizin anahtarını sessizce yine de benzersiz olmayan NCI anahtarına ekleyeceğini hatırlayın).Name,Id

Benzersiz olmayan bir kümelenmiş dizin, benzersizleştirici IDENTITYolarak işlev görmek üzere manuel olarak bir sütun eklenerek de elde edilebilir.

DECLARE @T TABLE
(
A INT NULL,
B INT NULL,
C INT NULL,
Uniqueifier INT NOT NULL IDENTITY(1,1),
UNIQUE CLUSTERED (A,Uniqueifier)
)

Ancak bu, benzersiz olmayan bir kümelenmiş dizinin normalde SQL Server'da gerçekte nasıl uygulanacağına dair doğru bir simülasyon değildir, çünkü bu, tüm satırlara "Benzersizleştirici" ekler. Sadece ihtiyacı olanlar değil.


1
Not: 2000-2012 çözümü yalnızca metin sütunu <= 900 bayt olduğunda çalışır. yani. varchar (900), nvarchar (450)
Andre Figueiredo

1
@AndreFigueiredo evet, bu sürümlerde de kalıcı tablolardaki bir dizin anahtarının maksimum boyutu.
Martin Smith

1
Sadece SQL 2014 yanıtının Azure'da iyi çalıştığını belirtmek istedim. Teşekkürler Martin!
Jaxidian

13

Performans açısından bakıldığında @temp tabloları ile #temp tabloları arasında değişkenleri destekleyen farklar olmadığı anlaşılmalıdır. Aynı yerde (tempdb) ikamet ederler ve aynı şekilde uygulanırlar. Tüm farklılıklar ek özelliklerde görünür. Bu inanılmaz derecede eksiksiz yazıya bakın: /dba/16385/whats-the-difference-between-a-temp-table-and-table-variable-in-sql-server/16386#16386

Tablo veya skaler işlevlerde olduğu gibi geçici bir tablonun kullanılamadığı durumlar olsa da, v2016'dan önceki diğer çoğu durumda (filtrelenmiş dizinler bile bir tablo değişkenine eklenebilir) basitçe #temp tablosu kullanabilirsiniz.

Tempdb'de adlandırılmış dizinleri (veya kısıtlamaları) kullanmanın dezavantajı, adların çakışabilmesidir. Sadece diğer prosedürlerle teorik olarak değil, aynı zamanda #temp tablosunun kopyasına aynı dizini koymaya çalışacak prosedürün diğer örnekleriyle kolayca kolayca.

İsim çatışmalarından kaçınmak için genellikle böyle bir şey çalışır:

declare @cmd varchar(500)='CREATE NONCLUSTERED INDEX [ix_temp'+cast(newid() as varchar(40))+'] ON #temp (NonUniqueIndexNeeded);';
exec (@cmd);

Bu, adın aynı prosedürün eşzamanlı yürütülmesi arasında bile benzersiz olmasını sağlar.



1
Adlandırılmış dizinlerle ilgili bir sorun yoktur - dizinlerin yalnızca bir tabloda benzersiz olarak adlandırılması gerekir. Sorun adlandırılmış kısıtlamalarla ilgilidir ve en iyi çözüm genellikle geçici tablolarda adlandırmak değildir - adlandırılmış kısıtlamalar geçici tablo nesnesi önbelleğini engeller.
Martin Smith

1
Bu yalnızca belirli sürümler için geçerli olmalıdır (herhangi bir sürüm için geçerliyse). Ben özellikle eşzamanlı yürütme sırasında adlandırılmış dizinler çatışma sp hataları takip çünkü bu geçici çözüm bulmak zorunda kaldı.
bielawski

@bielawski 2016 mı kullanıyorsunuz? Geçici tablolardaki adlandırılmış dizinlerin eşzamanlı ortamlar için risk olup olmadığını çok merak ediyorum.
Elaskanator

1
@Elaskanator evet, öyleler. Yük altındayken SQL meta veri tablolarında çekişme bulduk, dizinin adını kaldırmak sorunu çözdü. Bu SQL 2016'ydı.
Dan Def

0

Tablo değişkeni büyük verilere sahipse, tablo değişkeni (@table) yerine temp table (#table) .table değişkeni, ekleme işleminden sonra dizin oluşturulmasına izin vermez.

 CREATE TABLE #Table(C1 int,       
  C2 NVarchar(100) , C3 varchar(100)
  UNIQUE CLUSTERED (c1) 
 ); 
  1. Benzersiz kümelenmiş dizine sahip tablo oluşturma

  2. Temp "#Table" tablosuna veri ekleme

  3. Kümelenmemiş dizinler oluşturun.

     CREATE NONCLUSTERED INDEX IX1  ON #Table (C2,C3);

gereksiz sıralama önlemek için ekleme deyimi sonra dizin oluşturmak
Boopathi.Indotnet

Tablo değişkeni bir
Geoff
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.