Một chỉ số với tất cả các phím gần 900 byte sẽ rất lớn và rất sâu (rất ít phím trên mỗi trang dẫn đến các cây B rất cao).
Tùy thuộc vào cách bạn lập kế hoạch truy vấn giá trị. Chỉ mục hữu ích trong một số trường hợp:
- khi giá trị được thăm dò. Đây là cách sử dụng điển hình nhất, là khi một giá trị chính xác được tìm kiếm trong bảng. Ví dụ điển hình là
WHERE column='ABC'
hoặc điều kiện tham gia ON a.column = B.someothercolumn
.
- khi một phạm vi được quét. Điều này cũng khá điển hình khi một phạm vi của các giá trị được tìm kiếm trong bảng. Bên cạnh ví dụ rõ ràng của
WHERE column BETWEEN 'ABC' AND 'DEF'
còn có các ví dụ ít rõ ràng hơn khác, chẳng hạn như kết hợp từng phần: WHERE column LIKE 'ABC%'
.
- yêu cầu đặt hàng. Việc sử dụng này ít được biết đến hơn, nhưng các chỉ mục có thể giúp truy vấn có yêu cầu rõ ràng là
ORDER BY column
để tránh sắp xếp ngừng và cũng có thể giúp yêu cầu sắp xếp ẩn nhất định, chẳng hạn như ROW_NUMBER() OVER (ORDER BY column)
.
Vì vậy, tại sao bạn cần chỉ mục? Loại truy vấn nào sẽ sử dụng nó?
Để quét phạm vi và yêu cầu đặt hàng không có giải pháp nào khác nhưng phải có chỉ mục và bạn sẽ phải cân nhắc chi phí của chỉ mục so với lợi ích.
Đối với các đầu dò, bạn có thể sử dụng hàm băm để tránh lập chỉ mục một cột rất lớn. Tạo cột được tính liên tục là column_checksum = CHECKSUM(column)
và sau đó lập chỉ mục trên cột đó. Các truy vấn phải được viết lại để sử dụng WHERE column_checksum = CHECKSUM('ABC') AND column='ABC'
. Cần cân nhắc cẩn thận để cân nhắc lợi thế của một chỉ số hẹp (kiểm tra 32 bit) so với những bất lợi của việc kiểm tra va chạm đôi và thiếu khả năng quét và sắp xếp phạm vi.
sau khi bình luận
Tôi từng có một vấn đề tương tự và tôi đã sử dụng một cột băm. Giá trị quá lớn để chỉ mục (> 1K) và tôi cũng cần chuyển đổi giá trị thành ID để lưu trữ (về cơ bản, một từ điển). Một cái gì đó dọc theo dòng:
create table values_dictionary (
id int not null identity(1,1),
value varchar(8000) not null,
value_hash = checksum(value) persisted,
constraint pk_values_dictionary_id
primary key nonclustered (id));
create unique clustered index cdx_values_dictionary_checksum on (value_hash, id);
go
create procedure usp_get_or_create_value_id (
@value varchar(8000),
@id int output)
begin
declare @hash = CHECKSUM(@value);
set @id = NULL;
select @id = id
from table
where value_hash = @hash
and value = @value;
if @id is null
begin
insert into values_dictionary (value)
values (@value);
set @id = scope_identity();
end
end
Trong trường hợp này các bảng từ điển được tổ chức như một nhóm chỉ số trên cột values_hash
mà nhóm tất cả các giá trị băm va chạm với nhau. Cột id
được thêm vào để làm cho chỉ mục nhóm duy nhất, tránh sự cần thiết cho một hidden uniqueifier column. Cấu trúc này làm cho tra cứu cho @value
hiệu quả nhất có thể, với chỉ số cực kỳ không hiệu quả trên value
và bỏ qua giới hạn 900 ký tự. Khóa chính trên id
không được nhóm lại, có nghĩa là tra cứu value
từ và id
sẽ làm phát sinh chi phí của một đầu dò thêm trong chỉ mục nhóm.
Không chắc chắn nếu điều này giải đáp được vấn đề của bạn, bạn rõ ràng là biết nhiều hơn về các tình huống thực tế của bạn hơn tôi. Ngoài ra, mã không xử lý các điều kiện lỗi và thực sự có thể chèn các mục nhập @value trùng lặp, có thể có hoặc không chính xác.
Câu hỏi của bạn không đặc biệt hữu ích nếu không có ngữ cảnh. Tại sao bạn nghĩ rằng bạn cần một chỉ mục? Bạn sẽ sử dụng nó như thế nào? – Anon246
xem bình luận dưới đây Remus Rusanu – Ghita
bất cứ ai biết nếu nó muốn được hữu ích để sử dụng https://msdn.microsoft.com/en-us/library/ms174415.aspx nếu bạn phải sử dụng dây dài cho loại điều này. – HumbleWebDev