Hiệu suất chỉ mục cho CHAR vs VARCHAR (Postgres)


15

Trong câu trả lời này ( /programming/517579/strings-as-primary-keys-in-sql-database ) một nhận xét duy nhất lọt vào mắt tôi:

Ngoài ra, hãy nhớ rằng thường có sự khác biệt rất lớn giữa CHAR và VARCHAR khi thực hiện so sánh chỉ số

Điều này áp dụng / vẫn áp dụng cho Postgres?

Tôi đã tìm thấy các trang trên Oracle tuyên bố rằng CHARít nhiều là bí danh VARCHARvà vì vậy hiệu suất chỉ mục là như nhau, nhưng tôi không tìm thấy gì rõ ràng trên Postgres.

Câu trả lời:


24

CHARVARCHARđược thực hiện giống hệt nhau trong Postgres (và Oracle). Không có sự khác biệt về tốc độ khi sử dụng các loại dữ liệu đó.

Tuy nhiên, có một sự khác biệt có thể tạo ra sự khác biệt về hiệu suất: một charcột luôn được đệm theo chiều dài đã xác định. Vì vậy, nếu bạn xác định một cột là char(100)và một varchar(100)nhưng chỉ lưu 10 ký tự trong mỗi char(100)cột , thì cột sử dụng 100 ký tự cho mỗi giá trị (10 ký tự bạn đã lưu, cộng với 90 khoảng trắng), trong khi varcharcột chỉ lưu 10 ký tự.

So sánh 100 ký tự với 100 ký tự sẽ chậm hơn so với so sánh 10 ký tự với 10 ký tự - mặc dù tôi nghi ngờ bạn thực sự có thể đo lường sự khác biệt này trong truy vấn SQL.

Nếu bạn khai báo cả hai với độ dài 10 ký tự và luôn lưu trữ chính xác 10 ký tự trong đó, thì hoàn toàn không có sự khác biệt nào (điều này đúng với Oracle và Postgres)

Vì vậy, sự khác biệt duy nhất là phần đệm được thực hiện cho charkiểu dữ liệu.


Ngoài ra, hãy nhớ rằng thường có sự khác biệt rất lớn giữa CHAR và VARCHAR khi thực hiện so sánh chỉ số

Trích dẫn trên chỉ đúng nếu (và chỉ khi) charcột được xác định quá rộng (tức là bạn đang lãng phí không gian do phần đệm). Nếu độ dài của charcột luôn được sử dụng hoàn toàn (vì vậy không có phần đệm xảy ra), thì trích dẫn trên là sai (ít nhất là đối với Postgres và Oracle)


Theo quan điểm của tôi, charkiểu dữ liệu không thực sự có sử dụng từ thực. Chỉ cần sử dụng varchar(hoặc texttrong Postgres) và quên rằng chartồn tại.


2
So sánh 100 ký tự với 100 ký tự sẽ chậm hơn so với so sánh 10 ký tự với 10 ký tự - mặc dù tôi nghi ngờ bạn thực sự có thể đo lường sự khác biệt này trong truy vấn SQL. - Tùy thuộc vào những gì truy vấn ngoài việc sắp xếp, sự khác biệt có thể rất lớn. Đó là lý do tại sao Postgres 9,5 có một “phím tắt” tính năng mới: pgeoghegan.blogspot.de/2015/01/...
chirlu

6

Tôi đồng ý với mọi thứ được nói bởi a_horse_with_no_name và tôi thường đồng ý với lời khuyên nhận xét của Erwin:

Không, char kém hơn (và lỗi thời). văn bản và varchar thực hiện (gần như) giống nhau.

metadata

Với một ngoại lệ nhỏ, lần duy nhất tôi sử dụng char()là khi tôi muốn siêu dữ liệu nói điều này PHẢI có ký tự x. Mặc dù tôi biết rằng char()chỉ phàn nàn nếu đầu vào vượt quá giới hạn, tôi sẽ thường xuyên bảo vệ chống lại sự xâm nhập trong một CHECKràng buộc. Ví dụ,

CREATE TABLE foo (
  x char(10) CHECK ( length(x) = 10 )
);
INSERT INTO foo VALUES (repeat('x', 9));

Tôi làm điều này vì một vài lý do,

  1. char(x)đôi khi được suy ra với các trình tải lược đồ như là một cột có chiều rộng cố định. Điều này có thể tạo ra sự khác biệt trong ngôn ngữ được tối ưu hóa cho các chuỗi có độ rộng cố định.
  2. Nó thiết lập một quy ước có ý nghĩa và dễ dàng thực thi. Tôi có thể viết một trình nạp lược đồ bằng ngôn ngữ để tạo mã từ quy ước này.

Cần một ví dụ về nơi tôi có thể làm điều này,

  1. Tuy nhiên, viết tắt trạng thái hai chữ cái vì danh sách này có thể được liệt kê, tôi thường sẽ làm nó với một ENUM.
  2. Số nhận dạng xe
  3. Số mô hình (có kích thước cố định)

Lỗi

Lưu ý rằng một số người có thể không thoải mái với sự không phù hợp của thông báo lỗi ở cả hai phía của giới hạn, nhưng nó không làm phiền tôi

test=# INSERT INTO foo VALUES (repeat('x', 9));
ERROR:  new row for relation "foo" violates check constraint "foo_x_check"
DETAIL:  Failing row contains (xxxxxxxxx ).
test=# INSERT INTO foo VALUES (repeat('x', 11));
ERROR:  value too long for type character(10)

Tương phản với varchar

Hơn nữa, tôi nghĩ rằng gợi ý trên phù hợp thực sự tốt với một quy ước hầu như luôn luôn sử dụngtext . Bạn hỏi về varchar(n)quá. Tôi không bao giờ sử dụng nó . Ít nhất, tôi không thể nhớ lần cuối cùng tôi sử dụng varchar(n).

  • Nếu một thông số có trường độ rộng tĩnh mà tôi tin tưởng, tôi sử dụng char(n),
  • Mặt khác, tôi sử dụng textcó hiệu quả varchar(không giới hạn)

Nếu tôi tìm thấy một thông số có các khóa văn bản có độ dài thay đổi có ý nghĩa và tôi tin rằng nó có độ dài tối đa không đổi, tôi cũng sẽ sử dụng varchar(n). Tuy nhiên, tôi không thể nghĩ ra bất cứ điều gì phù hợp với tiêu chí đó.

Ghi chú bổ sung

Hỏi đáp liên quan:


1

Postgresql

sales_reporting_db=# create table x (y char(2));
CREATE TABLE
sales_reporting_db=# insert into x values ('Y');
INSERT 0 1
sales_reporting_db=# select '*' || y || '*' from x;
 ?column? 
----------
 *Y*

Oracle

SQL> create table x ( y char(2));

Table created.

SQL> insert into x values ('Y');

1 row created.

SQL> select '*' || y || '*' from x;

'*'|
----
*Y *

Postgresql không đệm với khoảng trắng.


Đó chỉ là ảo ảnh quang học trong Postgres. Hãy thửSELECT pg_column_size(y) FROM x;
dezso

-2

Tôi thấy điều này hữu ích nhất, và một lời giải thích 3 dòng nhanh:

Từ CHAR (n) Vs VARCHAR (N) Vs Text trong Postgres

  • Nếu bạn muốn lưu trữ một số văn bản có độ dài không xác định, hãy sử dụng TEXTkiểu dữ liệu.
  • Nếu bạn muốn lưu trữ một số văn bản có độ dài không xác định, nhưng bạn biết độ dài tối đa, hãy sử dụng VARCHAR(n).
  • Nếu bạn muốn lưu trữ một số văn bản với độ dài chính xác đã biết, hãy sử dụng CHAR(N).
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.