Sự khác biệt giữa các trường VARCHAR và INTEGER trong khóa
Tôi đang sử dụng ID kiểu số nguyên làm khóa chính trong các bảng của mình. Nếu tôi dùng trường varchar thay thế thì sao? Tôi có bị giảm hiệu suất trong trường hợp đó không, đặc biệt là với các bảng lớn? Các phép join có còn nhanh như với cột số nguyên không?
Hiệu suất của bạn sẽ gần như tương đương với varchar hoặc số nguyên. Firebird luôn so sánh các khóa chỉ mục theo từng byte và chỉ phần quan trọng của giá trị được lưu trữ.
Một khóa trường đơn trước tiên được chuyển đổi thành một trong ba loại chuẩn: chuỗi có collation, double precision, và (đáng tiếc là) số nguyên 64 bit. Ngày tháng trở thành số dấu phẩy động double precision.
Các chuỗi có collation khác với giá trị byte của chúng được chuyển đổi sang định dạng collation của chúng. Đó là một kiểu nghệ thuật khó hiểu và làm tăng kích thước của chuỗi, nhưng kết quả là chuỗi tìm đúng vị trí của nó khi được sắp xếp với các chuỗi khác cùng collation. ‘A’, ‘a’, ‘â’, ‘á’, ‘Ă’, ‘ã’, ‘ä’, ‘å’, ‘ă’, ‘ą’, ‘Ā’ đều xuất hiện ở đúng vị trí được chỉ định của chúng. (Xin lỗi vì điều đó đã làm gì với email client của bạn …. trong của tôi, đó là mười một biến thể của ‘A’.) Các khoảng trắng ở cuối không được bao gồm trong khóa.
Số double precision được xáo trộn để nó cũng sắp xếp theo từng byte - gần như đảo ngược dấu, sau đó là số mũ, rồi phần định trị, cắt bỏ các số không ở cuối.
Tùy thuộc vào endianness của số nguyên 64 bit trên máy tính, chúng cũng bị xáo trộn để so sánh theo từng byte. Điều đó có vẻ như là một sự tối ưu ngược, nhưng các khóa chỉ mục không được lưu trữ trên các ranh giới tự nhiên và chúng trải qua nén tiền tố nên không có cách nào để sử dụng phép so sánh lớn hơn từng byte một.
Các khóa tổng hợp cũng tương tự. Mỗi phần được chuyển đổi sang loại khóa chỉ mục của nó và được đệm thành bội số của 4 byte. Sau mỗi bốn byte, Firebird thêm một byte chứa vị trí của trường hiện tại trong khóa. Do đó, một chỉ mục trên LastName, FirstName, ZodiacSign sẽ ra thành 1Harr1ison2Ann 3Gemi3ni. Điều này tránh sự bối rối khi nhầm lẫn Damnation với Dam nation.
Tại sao tôi nói “(đáng tiếc là)” ở trên? Bởi vì có một định dạng duy nhất cho số cho phép Firebird thay đổi kích thước của số mà không cần tạo lại chỉ mục trên chúng. Nhưng khi Borland thêm số nguyên 64 bit trở lại - InterBase đã có số nguyên 64 bit ngay từ đầu trên các máy Vax - một số người thông minh nhận ra rằng double precision có 56 bit độ chính xác và số nguyên 64 bit có 64 bit. Mặt khác, các chỉ mục của Firebird được thiết kế để xử lý một số độ thiếu chính xác … hoặc 8 bit còn lại có thể được gắn vào cuối … sao cũng được. Vì vậy, bạn phải xây dựng lại chỉ mục khi chuyển từ Numeric/Decimal 9 sang Numeric/Decimal 12. Đáng buồn.
“Nén tiền tố?” Khi lưu trữ một khóa không phải là khóa đầu tiên trên một trang hoặc khóa đầu tiên sau một bước nhảy trên trang, Firebird nhìn vào khóa trước đó và cắt bỏ phần đầu của khóa tiếp theo trùng với khóa trước đó và gắn độ dài của phần bị cắt vào đầu. Do đó, các chuỗi “AAAA”, “AAAB”, “AAAC”, “AABC” trở thành
“AAAA”, “3B”, “3C”, và “2BC”. Có một vấn đề với một số định dạng GUID đặt phần thay đổi của số lên đầu, tiếp theo là phần cố định. Điều đó làm hỏng nén tiền tố và làm tăng kích thước của chỉ mục.
“Bước nhảy?” - Nén tiền tố làm giảm kích thước của chỉ mục rất nhiều, giảm I/O, nhưng yêu cầu đọc qua toàn bộ trang để giải mã khóa. Ổn với trang 1K, nhưng với kích thước trang lớn hơn thì việc tính toán là không thể chấp nhận được. Vì vậy, mỗi trang chỉ mục hiện có một chỉ mục riêng của nó trỏ đến các offset của các mục không nén. Chỉ mục đó được gọi là jump vector.
Ann Harrision