2011-11-03 38 views
8

Tôi có một bảng có một khóa chuỗi lớn (varchar (1024)) mà tôi đã suy nghĩ để được lập chỉ mục trên trên máy chủ SQL (Tôi muốn để có thể tìm kiếm trên nó một cách nhanh chóng mà còn chèn là quan trọng). Trong sql 2008 tôi không nhận được cảnh báo về điều này, nhưng dưới máy chủ sql 2005 nó cho tôi biết rằng nó vượt quá 900 byte và chèn/cập nhật với cột trên kích thước này sẽ bị loại bỏ (hoặc cái gì đó trong khu vực đó)Máy chủ SQL - có giá trị lập chỉ mục các khóa chuỗi lớn?

Lựa chọn thay thế của tôi là gì nếu tôi muốn lập chỉ mục trên cột lớn này? Tôi không biết liệu nó có đáng giá không nếu tôi có thể.

+1

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

+0

xem bình luận dưới đây Remus Rusanu – Ghita

+0

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

Trả lời

13

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.

+0

Cảm ơn bạn đã chỉ ra rằng Remus. Điều đó thực sự có ý nghĩa. Tôi nghĩ rằng tôi chủ yếu sử dụng cột này tại chèn cho vị trí nếu nó đã có (và nó liên quan đến hàng duy nhất id) để tôi có thể tham khảo id của cột đó là chìa khóa nước ngoài trong bảng khác. Điều đó có ý nghĩa :-)? Vì vậy, chủ yếu cho trường hợp được mô tả: WHERE column = 'ABC' – Ghita

+0

+1, tôi nghĩ về việc thêm chỉ mục vào cột băm, nhưng tự hỏi phải làm gì với va chạm, không bao giờ nghĩ đến việc có chỉ mục trên BOTH cột băm và cột id. –

1

General Index Design Guidelines

Khi bạn thiết kế một chỉ số xem xét chủ trương cột sau:

  • Giữ độ dài của chỉ số chủ chốt viết tắt của chỉ số nhóm. Ngoài ra, các chỉ mục nhóm được lợi từ việc được tạo trên các cột hoặc không phải là duy nhất. Để biết thêm thông tin, hãy xem Hướng dẫn thiết kế chỉ mục theo cụm Hướng dẫn.

  • Cột thuộc loại văn bản ntext, văn bản, hình ảnh, varchar (max), nvarchar (max) và varbinary (max) không thể được chỉ định là các cột khóa chỉ mục. Tuy nhiên, các loại dữ liệu varchar (max), nvarchar (max), varbinary (max) và xml có thể tham gia vào một chỉ số không được chỉ định dưới dạng cột chỉ mục không phải là cột. Để biết thêm thông tin, hãy xem Chỉ mục với Cột được bao gồm.

  • Kiểm tra phân phối dữ liệu trong cột. Thông thường, một truy vấn dài hạn được gây ra bởi việc lập chỉ mục một cột có ít giá trị duy nhất hoặc bằng cách thực hiện kết nối trên cột như vậy. Đây là vấn đề cơ bản với dữ liệu và truy vấn và thường không thể được giải quyết mà không cần xác định tình huống này. Ví dụ, một điện thoại thư mục vật lý được sắp xếp theo thứ tự abc vào tên cuối cùng sẽ không đẩy nhanh định vị một người nếu tất cả mọi người trong thành phố được đặt tên Smith hay Jones

+0

Vì vậy, về cơ bản trong trường hợp của tôi, nơi tôi có cột varchar lớn này, tôi sẽ chỉ phải dính vào không sử dụng một chỉ mục ở tất cả? Tôi cũng là một ví dụ về liên kết được cung cấp: TẠO INDEX IX_Address_PostalMã số TRÊN Person.Address (PostalCode) BAO GỒM (AddressLine1, AddressLine2, City, StateProvinceID); Trong ví dụ được cung cấp, có vẻ như chỉ có Mã Bưu điện được tính trên kích thước chỉ mục. Điều này có giúp hiệu suất ở tất cả khi truy vấn trên cột AddressLine1 (ví dụ: "WHERE AddressLine1 = @ Addr1") không? – Ghita

Các vấn đề liên quan