Chỉ mục tra cứu sẽ nhanh hơn đáng kể với char vs varchar khi tất cả các giá trị là 36 ký tự


30

Tôi có một lược đồ kế thừa (từ chối trách nhiệm!) Sử dụng id được tạo dựa trên hàm băm cho khóa chính cho tất cả các bảng (có rất nhiều). Một ví dụ về id như vậy là:

922475bb-ad93-43ee-9487-d2671b886479

Không có hy vọng có thể thay đổi cách tiếp cận này, tuy nhiên hiệu suất với truy cập chỉ mục là kém. Đặt ra vô số lý do có thể xảy ra, có một điều tôi nhận thấy rằng dường như ít hơn tối ưu - mặc dù tất cả các giá trị id trong tất cả các bảng có độ dài chính xác 36 ký tự, nhưng kiểu cột varchar(36)thì không char(36) .

Việc thay đổi các loại cột thành độ dài cố định char(36)sẽ cung cấp bất kỳ lợi ích hiệu suất chỉ mục đáng kể nào , ngoài việc tăng rất ít số lượng mục trên mỗi trang chỉ mục, v.v.?

Tức là postgres thực hiện nhanh hơn nhiều khi xử lý các loại có độ dài cố định so với các loại có độ dài thay đổi?

Vui lòng không đề cập đến việc tiết kiệm lưu trữ cực nhỏ - điều đó sẽ không thành vấn đề so với phẫu thuật cần thiết để thực hiện thay đổi cho các cột.

Câu trả lời:


40

Không . Không có lợi ích gì cả . Hướng dẫn nêu rõ :

Mẹo: Không có sự khác biệt về hiệu suất giữa ba loại này , ngoài không gian lưu trữ tăng lên khi sử dụng loại đệm trống và một vài chu kỳ CPU bổ sung để kiểm tra độ dài khi lưu trữ vào cột bị giới hạn độ dài. Mặc dù character(n)có lợi thế về hiệu năng trong một số hệ thống cơ sở dữ liệu khác, nhưng PostgreSQL không có lợi thế như vậy; trong thực tế character(n)thường là chậm nhất trong ba vì chi phí lưu trữ bổ sung của nó. Trong hầu hết các tình huống text hoặc character varyingnên được sử dụng thay thế .

Nhấn mạnh đậm của tôi.

char(n)là một loại phần lớn lỗi thời, vô dụng. Gắn bó với varchar(n). Nếu bạn không cần phải thực thi độ dài, varcharhoặc textsẽ nhanh hơn một chút. Bạn sẽ không thể đo lường sự khác biệt.

Ngoài ra, nếu tất cả các chuỗi có độ dài chính xác 36 ký tự, thì không có cách lưu trữ nào cả, thậm chí không phải là một chuỗi rất nhỏ. Cả hai đều có cùng kích thước trên đĩa và trong RAM. Bạn có thể kiểm tra với pg_column_size()(trên một biểu thức và trên cột bảng).

Liên quan:

Bạn đã không yêu cầu các tùy chọn khác , nhưng tôi sẽ đề cập đến hai:

  1. COLLATION- trừ khi bạn đang chạy DB của mình với đối chiếu "C" . Đối chiếu thường bị bỏ qua và có thể đắt tiền. Vì các chuỗi của bạn dường như không có ý nghĩa trong ngôn ngữ tự nhiên, có lẽ không có điểm nào trong các COLLATIONquy tắc sau . Liên quan:

    So sánh điểm chuẩn mở rộng (trong số khác) ảnh hưởng của COLLATE "C"hiệu suất:

  2. UUID , rõ ràng. Chuỗi của bạn trông đáng ngờ giống như một UUID (32 chữ số hex cộng với 4 dấu phân cách). Sẽ hiệu quả hơn nhiều nếu lưu trữ chúng dưới dạnguuiddữ liệuthực tế, nhanh hơn theo nhiều cách và chỉ chiếm 16 byte - trái ngược với 37 byte trong RAM cho mộtchar(36)hoặcvarchar(36)(được lưu trữ mà không có dấu phân cách, chỉ là 32 định nghĩa char) hoặc 33 byte trên đĩa. Nhưng phần đệm căn chỉnh sẽ dẫn đến 40 byte trong cả hai trường hợp.) CũngCOLLATIONkhông liên quan đếnuuidkiểu dữ liệu.

    SELECT '922475bb-ad93-43ee-9487-d2671b886479'::uuid

    Điều này có thể hữu ích (chương cuối):

    Xem thêm:


điều này có nghĩa là char / varchar (n) bị ràng buộc độ dài sẽ sử dụng chu kỳ CPU để kiểm tra ràng buộc trong khi trường văn bản có độ dài thay đổi sẽ lưu trữ văn bản riêng theo cách ít truy cập hơn so với char, người chiến thắng trong kịch bản này và đây là chiến thắng thậm chí đáng để xem xét khi nói 10 triệu hàng với một đoạn văn bản
PirateApp

1
@PirateApp: char(n)gần như không bao giờ thắng trong bất kỳ khía cạnh nào. Đừng sử dụng nó. Các kiểu dữ liệu textvarchar(không có công cụ sửa đổi độ dài) tương thích nhị phân và có chung đặc điểm hiệu suất. Có những lý do lịch sử để cả hai cùng tồn tại trong Postgres. Trong nội bộ, textlà loại "ưa thích" trong số các loại chuỗi (có thể ảnh hưởng đến độ phân giải loại hàm). Các chu kỳ CPU để thực thi varchar(n)hầu như không có vấn đề. Sử dụng một giới hạn độ dài khi bạn cần nó. Trong trường hợp trong tầm tay uuidlà người chiến thắng thực sự.
Erwin Brandstetter
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.