Tạo một chỉ mục trên một biến bảng


189

Bạn có thể tạo một chỉ mục trên một biến bảng trong SQL Server 2000 không?

I E

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

Tôi có thể tạo một chỉ mục trên Namekhông?


3
Có một chi phí trong việc tạo cả hai loại bảng tạm thời; và nếu bạn có quá nhiều dữ liệu đến mức bạn cần một chỉ mục thì có lẽ đã đến lúc xem xét bằng cách sử dụng một bảng thực; mà bạn thiết lập để được giao dịch an toàn; lọc theo spid hoặc id người dùng và sau đó xóa nó ở cuối. Các bảng thực v và các bảng tạm thời đều có những thăng trầm nhưng nếu hiệu suất là một vấn đề; Hãy thử nó với một bảng thực sự quá.
u07ch

Một bảng tạm thời 'LÀ' một bảng thực sự, nó sẽ biến mất khi bạn hoàn thành. Sự khác biệt thực sự (khác với nó sẽ tự động biến mất) là ở TempDB. Điều này thực sự rất lớn khi nói đến các chỉ mục và các ràng buộc bởi vì bạn có thể kết thúc bằng các xung đột tên, không chỉ với các lần thực thi mã khác mà còn thực thi mã trong các cơ sở dữ liệu khác trong ví dụ của bạn.
bielawski

@bielawski đây là biến bảng không phải là bảng tạm thời. Các biến bảng không cho phép các ràng buộc được đặt tên rõ ràng, các tên được tạo bởi hệ thống được đảm bảo là duy nhất. Chúng cho phép các chỉ mục được đặt tên từ năm 2014 nhưng đó không phải là vấn đề vì các chỉ mục chỉ cần được đặt tên duy nhất trong một đối tượng không nằm trên các đối tượng.
Martin Smith

Quan điểm của tôi là 2 lần. 1) Khác với việc sử dụng một biến để tránh sự vướng mắc giao dịch, không có sự khác biệt về vật chất giữa một bảng tạm thời và biến bảng. Tuy nhiên, trong V-2000 không có cú pháp để thêm các ràng buộc, chỉ mục ... vào một biến. 2) Thay vào đó, người ta có thể sử dụng bảng tạm thời, các phụ lục của bảng được đặt tên như chỉ mục SILL xung đột với việc thực hiện đồng thời các bản sao của cùng một SP nếu sử dụng tên tĩnh! Cơ chế dưới đây được phát triển một cách rõ ràng bởi vì tôi đã tìm ra các lỗi SP được đặt tên là xung đột trong các trường hợp chính xác này. Họ PHẢI là duy nhất.
bielawski

1
@bielawski - Không có tên chỉ mục nào không cần phải là duy nhất giữa các đối tượng - chỉ có tên ràng buộc mới làm. Đây là chuyện nhỏ để kiểm tra. Chỉ cần thực hiệnCREATE TABLE #T1(X INT); CREATE TABLE #T2(X INT); CREATE INDEX IX ON #T1(X); CREATE INDEX IX ON #T2(X);
Martin Smith

Câu trả lời:


362

Câu hỏi được gắn thẻ SQL Server 2000 nhưng vì lợi ích của những người phát triển trên phiên bản mới nhất trước tiên tôi sẽ giải quyết vấn đề đó.

Máy chủ SQL 2014

Ngoài các phương pháp thêm các chỉ mục dựa trên ràng buộc được thảo luận bên dưới SQL Server 2014 cũng cho phép các chỉ mục không duy nhất được chỉ định trực tiếp bằng cú pháp nội tuyến trên các khai báo biến bảng.

Cú pháp ví dụ cho điều đó là dưới đây.

/*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*/
);

Các chỉ mục và chỉ mục được lọc với các cột được bao gồm hiện không thể được khai báo bằng cú pháp này tuy nhiên SQL Server 2016 giúp thư giãn điều này hơn một chút. Từ CTP 3.1, giờ đây có thể khai báo các chỉ mục được lọc cho các biến bảng. Theo RTM, thể trường hợp bao gồm các cột cũng được cho phép nhưng vị trí hiện tại là chúng "có thể sẽ không được đưa vào SQL16 do hạn chế tài nguyên"

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

Máy chủ SQL 2000 - 2012

Tôi có thể tạo một chỉ mục trên Tên không?

Câu trả lời ngắn gọn: Có.

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

Một câu trả lời chi tiết hơn dưới đây.

Các bảng truyền thống trong SQL Server có thể có một chỉ mục được nhóm hoặc được cấu trúc thành các đống .

Các chỉ mục được nhóm có thể được khai báo là duy nhất để không cho phép các giá trị khóa trùng lặp hoặc mặc định thành không duy nhất. Nếu không phải là duy nhất thì SQL Server âm thầm thêm một bộ duy nhất vào bất kỳ khóa trùng lặp nào để làm cho chúng là duy nhất.

Các chỉ mục không được nhóm cũng có thể được khai báo rõ ràng là duy nhất. Mặt khác, đối với trường hợp không phải là duy nhất, SQL Server thêm trình định vị hàng (khóa chỉ mục được nhóm hoặc RID cho một heap) cho tất cả các khóa chỉ mục (không chỉ trùng lặp) điều này một lần nữa đảm bảo chúng là duy nhất.

Trong SQL Server 2000 - 2012, chỉ mục trên các biến bảng chỉ có thể được tạo hoàn toàn bằng cách tạo UNIQUEhoặc PRIMARY KEYràng buộc. Sự khác biệt giữa các loại ràng buộc này là khóa chính phải nằm trên (các) cột không null. Các cột tham gia vào một ràng buộc duy nhất có thể là null. (mặc dù việc triển khai các ràng buộc duy nhất của SQL Server với sự hiện diện của NULLs không theo quy định trong Tiêu chuẩn SQL). Ngoài ra một bảng chỉ có thể có một khóa chính nhưng có nhiều ràng buộc duy nhất.

Cả hai ràng buộc logic này được thực hiện bằng vật lý với một chỉ mục duy nhất. Nếu không được chỉ định rõ ràng nếu không thì PRIMARY KEYsẽ trở thành chỉ mục được nhóm và các ràng buộc duy nhất không được phân cụm nhưng hành vi này có thể được ghi đè bằng cách chỉ định CLUSTEREDhoặc NONCLUSTEREDrõ ràng bằng khai báo ràng buộc (Cú pháp ví dụ)

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

Kết quả của các chỉ mục sau đây có thể được tạo hoàn toàn trên các biến bảng trong SQL Server 2000 - 2012.

+-------------------------------------+-------------------------------------+
|             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                                 |
+-------------------------------------+-------------------------------------+

Điều cuối cùng đòi hỏi một chút giải thích. Trong định nghĩa biến bảng ở đầu câu trả lời này, chỉ mục không phân cụm không duy nhất trên Nameđược mô phỏng bởi một chỉ mục duy nhất trên Name,Id(nhắc lại rằng SQL Server sẽ âm thầm thêm khóa chỉ mục được phân cụm vào khóa NCI không duy nhất).

Một chỉ mục cụm không duy nhất cũng có thể đạt được bằng cách thêm thủ công một IDENTITYcột để hoạt động như một công cụ duy nhất.

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

Nhưng đây không phải là một mô phỏng chính xác về cách một chỉ mục cụm không duy nhất thường thực sự được triển khai trong SQL Server vì điều này thêm "Trình duy nhất" vào tất cả các hàng. Không chỉ những người yêu cầu nó.


1
Lưu ý: Giải pháp 2000-2012 chỉ hoạt động nếu cột văn bản <= 900 byte. I E. varchar (900), nvarchar (450)
Andre Figueiredo

1
@AndreFigueiredo yep, đó là kích thước tối đa cho khóa chỉ mục trên các bảng cố định trong các phiên bản đó.
Martin Smith

1
Tôi chỉ muốn lưu ý rằng câu trả lời SQL 2014 hoạt động tốt trong Azure. Cảm ơn Martin!
Jaxidian

13

Cần hiểu rằng từ quan điểm hiệu suất, không có sự khác biệt giữa các bảng @temp và các bảng #temp ủng hộ các biến. Họ cư trú ở cùng một nơi (tempdb) và được thực hiện theo cùng một cách. Tất cả sự khác biệt xuất hiện trong các tính năng bổ sung. Xem bài viết hoàn chỉnh đáng kinh ngạc này: /dba/16385/whats-the-difference-b between-a-Can-table-and-could-variable-in-sql-server / 16386 # 16386

Mặc dù có những trường hợp không thể sử dụng bảng tạm thời như trong các hàm bảng hoặc vô hướng, nhưng đối với hầu hết các trường hợp khác trước v2016 (trong đó các chỉ mục được lọc thậm chí có thể được thêm vào biến bảng), bạn chỉ cần sử dụng bảng #temp.

Hạn chế của việc sử dụng các chỉ mục được đặt tên (hoặc các ràng buộc) trong tempdb là các tên sau đó có thể xung đột. Về mặt lý thuyết không chỉ với các thủ tục khác mà thường khá dễ dàng với các phiên bản khác của chính thủ tục sẽ cố gắng đặt cùng một chỉ mục trên bản sao của bảng #temp.

Để tránh xung đột tên, một cái gì đó như thế này thường hoạt động:

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

Điều này đảm bảo tên luôn luôn là duy nhất ngay cả giữa các lần thực hiện đồng thời của cùng một thủ tục.


Nó có một dấu ngoặc bị thiếu sau varchar (40), thêm vào đó
Tejasvi Hegde

1
Không có vấn đề với các chỉ mục được đặt tên - các chỉ mục chỉ phải được đặt tên duy nhất trong một bảng. Vấn đề là với các ràng buộc được đặt tên và giải pháp tốt nhất thường là không đặt tên chúng trong các bảng tạm thời - các ràng buộc được đặt tên ngăn chặn bộ đệm ẩn đối tượng của bảng tạm thời.
Martin Smith

1
Điều đó phải đúng chỉ với một số phiên bản nhất định (nếu nó đúng với bất kỳ phiên bản nào). Tôi đã phải đưa ra cách giải quyết này một cách cụ thể bởi vì tôi đã tìm ra những thất bại của sp đối với sự xung đột của các chỉ mục được đặt tên trong các lần thực thi đồng thời.
bielawski

@bielawski Bạn đang sử dụng 2016? Tôi rất tò mò về việc liệu các chỉ mục được đặt tên trên các bảng tạm thời có gây rủi ro cho các môi trường đồng thời hay không.
Elaskanator

1
@Elaskanator có, họ là. Chúng tôi đã tìm thấy sự tranh chấp trong các bảng dữ liệu meta SQL khi đang tải, loại bỏ tên của chỉ mục đã giải quyết vấn đề. Đây là SQL 2016.
Dan Def

0

Nếu biến Bảng có dữ liệu lớn, thì thay vì biến bảng (@table) tạo bảng tạm thời (#table) .table biến không cho phép tạo chỉ mục sau khi chèn.

 CREATE TABLE #Table(C1 int,       
  C2 NVarchar(100) , C3 varchar(100)
  UNIQUE CLUSTERED (c1) 
 ); 
  1. Tạo bảng với chỉ mục cụm duy nhất

  2. Chèn dữ liệu vào bảng "#Table" Temp

  3. Tạo các chỉ mục không cụm.

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

tạo chỉ mục sau khi chèn câu lệnh để tránh sắp xếp không cần thiết
Boopathi.Inotnet

Lưu ý rằng điều này là không thể nếu biến bảng nằm trong hàm
Geoff
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.