2009-10-21 33 views
7

Đây là một Bảng FACT trong một Data WarehouseIndexing Performance bigint vs VARCHAR

Nó có một chỉ số tổng hợp như sau

ALTER TABLE [dbo].[Fact_Data] 
ADD CONSTRAINT [PK_Fact_Data] 
PRIMARY KEY CLUSTERED 
(
    [Column1_VarChar_10] ASC, 
    [Column2_VarChar_10] ASC, 
    [Column3_Int] ASC, 
    [Column4_Int] ASC, 
    [Column5_VarChar_10] ASC, 
    [Column6_VarChar_10] ASC, 
    [Column7_DateTime] ASC, 
    [Column8_DateTime] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, 
SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, 
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON 
) ON [PRIMARY] 
GO 

Trong cấu trúc này, tất cả các varchar 10 cột có chỉ giá trị số. Tôi có thay đổi cấu trúc hàng 78 triệu để giữ BIGINT thay vì VARCHAR về truy vấn và lập chỉ mục không?

Bất kỳ lợi ích/hạn chế nào khác mà tôi nên cân nhắc?

Trả lời

14

Bạn nên DEFINITELY giới thiệu người thay thế INT IDENTITY() khóa chính !! INT đã cung cấp cho bạn khả năng lên đến 2 tỷ hàng - không đủ sao?

Khóa chính/cụm chính này trên SQL Server sẽ có kích thước tối đa 64 byte (thay vì 4, cho INT) - sẽ làm cho chỉ mục nhóm của bạn và tất cả chỉ mục không được nhóm của bạn bị cồng kềnh. Toàn bộ khóa phân cụm (tất cả 8 cột của bạn) sẽ được bao gồm trên mỗi trang của mỗi chỉ mục không nhóm trên bảng đó - lãng phí rất nhiều và rất nhiều không gian cho chắc chắn. Vì vậy, trên bất kỳ bảng chỉ mục cụ thể nào, bạn sẽ có tới 16 lần mục nhập với khóa thay thế INT nhóm - điều đó có nghĩa là rất ít I/O, tốn ít thời gian hơn khi đọc các trang chỉ mục.

Và hãy tưởng tượng cố gắng thiết lập mối quan hệ khóa ngoài với bảng .... bất kỳ bảng con nào sẽ phải có tất cả 8 cột của khóa chính làm cột khóa ngoài và chỉ định tất cả 8 cột trong mỗi cột tham gia - những gì một cơn ác mộng !!

Tại 78 triệu hàng, thậm chí chỉ cần thay đổi khóa phân cụm thành INTENTENTITY sẽ giúp bạn tiết kiệm tối đa 60 byte mỗi hàng - chỉ riêng bạn sẽ có tới 4 GB dung lượng đĩa (và sử dụng RAM trong máy chủ của bạn) . Và điều đó thậm chí không bắt đầu tính toán khoản tiết kiệm trên các chỉ mục không được nhóm .......

Và tất nhiên, vâng, tôi cũng sẽ thay đổi VARCHAR (10) thành INT hoặc BIGINT - nếu đó là số , làm cho kiểu trường số - không có điểm nào để để nó ở VARCHAR (10), thực sự. Nhưng điều đó một mình sẽ không tạo ra sự khác biệt lớn về mặt tốc độ hay hiệu suất - nó chỉ làm việc với dữ liệu dễ dàng hơn nhiều (không phải luôn bỏ qua các loại số khi ví dụ như so sánh các giá trị và vv).

Marc

+1

đây là bảng thực tế trong kho dữ liệu của tôi. không có bảng nào sử dụng PK từ đây như là một FK. –

+0

@Raj: ah, ok, điều đó giải thích một vài điều - bạn quên đề cập đến điều đó. Nhưng vẫn: bạn có các chỉ số không nhóm trên bảng này không? Những người chắc chắn sẽ cực kỳ quan trọng khi có một INT hoặc BIGINT chính/clustering key –

+0

Bigint sử dụng 64 BITS không phải byte, tức là nó lớn gấp đôi, không phải 16 lần. – Yrlec

1

Marc S là đúng trong đó 64 byte khóa chính sẽ được sao lại vào mỗi chỉ số NC, do đó bạn sẽ phải trả một chi phí I/O, mà sẽ ảnh hưởng đến số lượng dữ liệu mà được lưu trữ trong bộ nhớ (vì bạn đang lãng phí không gian trên trang chỉ mục NC). Vì vậy, trên cơ sở đó, câu hỏi không phải là 'tôi nên chuyển đổi các varchars của tôi' nhưng 'tôi nên xem xét chuyển đổi chỉ số nhóm của mình thành một cái gì đó hoàn toàn khác biệt./

Về mặt varchar so với bigint đó là một lý do tốt để chuyển đổi nếu bạn có thể đủ thời gian; đó là ngoài sự khác biệt 2 byte trong lưu trữ cho mỗi trường, khi bạn so sánh các giá trị có hai loại khác nhau, SQL sẽ buộc phải chuyển đổi một trong số chúng. Điều này sẽ xảy ra trên mọi so sánh đơn lẻ, cho dù đó là để tham gia chỉ mục hay một biến vị ngữ trong mệnh đề where.

Tùy thuộc vào những gì bạn đang chọn dữ liệu, bảng thứ nguyên nào được kết hợp với bảng thực tế, bạn có thể chọn chi phí chuyển đổi trên mỗi truy vấn để tham gia, vì nó phải chuyển đổi một mặt nó.

4

Hai điều đó có thể ảnh hưởng đến chỉ số (và DB tổng thể) thực hiện:

1) Kích thước của trang index tốc độ 2) So sánh

Vì vậy, cho là người đầu tiên, nói chung các bạn nhỏ hơn chỉ số/dữ liệu trang, càng có nhiều trang bạn có thể giữ trong bộ nhớ và khả năng truy vấn nhất định sẽ có thể tìm thấy trang trong bộ nhớ cache so với đĩa chậm. Vì vậy, bạn muốn sử dụng kiểu dữ liệu nhỏ nhất có thể thoải mái phù hợp với nhu cầu hiện tại và được đề xuất trong tương lai của bạn.

BigInt là 8 byte; VARCHAR có thể nhỏ hơn nếu kích thước của dữ liệu nhỏ, vì vậy nó thực sự phụ thuộc vào dữ liệu của bạn. Tuy nhiên, số lượng dài 10 ký tự có thể phù hợp với kiểu dữ liệu INT của SQL Server (http://msdn.microsoft.com/en-us/library/ms187745.aspx) tùy thuộc vào kích thước, do đó, int so với bigint phụ thuộc vào miền của bạn.

Ngoài ra, nếu toàn bộ hàng của bạn có độ dài cố định, có một số tối ưu nhất định mà SQL Server có thể thực hiện trong quá trình quét vì nó biết chính xác vị trí trên đĩa tiếp theo (giả sử các hàng tiếp giáp). Một trường hợp cạnh, để chắc chắn, nhưng nó có thể giúp đỡ.

Đối với số thứ hai, nhanh hơn so sánh các số nguyên so với chuỗi unicode. Vì vậy, nếu bạn chỉ lưu trữ dữ liệu số, bạn chắc chắn nên chuyển sang kiểu dữ liệu số có kích thước thích hợp.

Cuối cùng, Marc là chính xác rằng điều này trở thành một khóa chính rất phức tạp. Tuy nhiên, nếu dữ liệu của bạn đảm bảo - chẳng hạn như các cột CHỈ của bạn và bạn không bao giờ thực hiện các truy vấn add'l - bạn có thể hoàn toàn ổn định làm phiên bản được tối ưu hóa (với Bigints, vv) khóa chính của bạn. Loại mùi mã, mặc dù, vì vậy tôi sẽ lặp lại lời khuyên của anh ta để thực sự xem xét mô hình dữ liệu của bạn và xem điều này có đúng không.