Chi phí cho varchar (n) là gì?


15

Tôi muốn hỏi ý nghĩa của đoạn này từ tài liệu Postgres liên quan đến varchar(n)loại:

Yêu cầu lưu trữ cho một chuỗi ngắn (tối đa 126 byte) là 1 byte cộng với chuỗi thực tế, bao gồm phần đệm không gian trong trường hợp ký tự. Chuỗi dài hơn có 4 byte phí thay vì 1.

Hãy giả sử rằng tôi có một varchar(255)lĩnh vực. Và bây giờ, các tuyên bố sau:

  • Nếu trường này chứa một chuỗi 10 byte, thì chi phí là 1 byte. Vì vậy, chuỗi sẽ sử dụng 11 byte.
  • Nếu trường giữ chuỗi sử dụng 140 byte, thì chi phí là 4 byte. Vì vậy, chuỗi sẽ sử dụng 144 byte.

Những tuyên bố trên có đúng không? Ở đây ai đó hiểu tài liệu giống như tôi nhưng ở đây có người nói rằng chi phí luôn là 4 byte ở đây ?

Câu trả lời:


19

Không có gì đáng ngạc nhiên, hướng dẫn là đúng. Nhưng có nhiều hơn cho nó.

Đối với một, kích thước trên đĩa (trong bất kỳ bảng nào , ngay cả khi không thực sự được lưu trữ trên đĩa) có thể khác với kích thước trong bộ nhớ . Trên đĩa, chi phí chung cho varcharcác giá trị ngắn lên tới 126 byte được giảm xuống còn 1 byte như được nêu trong hướng dẫn. Nhưng tổng phí trong bộ nhớ luôn là 4 byte (một khi các giá trị riêng lẻ được trích xuất).

Điều này cũng đúng đối với text, varchar, varchar(n)hoặcchar(n) - ngoại trừ việc char(n)là trống-đệm để nnhân vật và bạn thường không muốn sử dụng nó. Kích thước hiệu quả của nó vẫn có thể thay đổi trong mã hóa nhiều byte vì nbiểu thị tối đa các ký tự, không phải byte:

chuỗi dài đến nký tự (không phải byte).

Tất cả đều sử dụng varlenanội bộ.
"char"(với dấu ngoặc kép) là một sinh vật khác nhau và luôn chiếm một byte đơn.
Chuỗi ký tự không được đánh dấu ( 'foo') có một byte trên đầu. Đừng nhầm lẫn với các giá trị đánh máy!

Kiểm tra với pg_column_size().

CREATE TEMP TABLE t (id int, v_small varchar, v_big varchar);
INSERT INTO t VALUES (1, 'foo', '12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890');

SELECT pg_column_size(id)        AS id
     , pg_column_size(v_small)   AS v_small
     , pg_column_size(v_big)     AS v_big
     , pg_column_size(t)         AS t
FROM   t
UNION ALL  -- 2nd row measuring values in RAM
SELECT pg_column_size(1)
     , pg_column_size('foo'::varchar)
     , pg_column_size('12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890'::varchar)
     , pg_column_size(ROW(1, 'foo'::varchar, '12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890'::varchar));

 id | v_small | v_big |  t
----+---------+-------+-----
  4 |       4 |   144 | 176
  4 |       7 |   144 | 176

Bạn có thể thấy:

  • Chuỗi 3 byte 'foo' chiếm 4 byte trên đĩa và 7 byte trong RAM (vì vậy 1 byte so với 4 byte trên không).
  • Chuỗi 140 byte '123 ...' chiếm 144 byte cả trên đĩa và trong RAM (vì vậy luôn có 4 byte trên không).
  • Lưu trữ integerkhông có chi phí hoạt động (nhưng nó có các yêu cầu căn chỉnh có thể áp đặt phần đệm).
  • Hàng có tổng phí bổ sung là 24 byte cho tiêu đề tuple (cộng thêm 4 byte cho mỗi tuple cho con trỏ mục trong tiêu đề trang).
  • Và cuối cùng nhưng không kém phần quan trọng: Chi phí nhỏ varcharvẫn chỉ là 1 byte trong khi nó chưa được trích xuất từ ​​hàng - như có thể thấy từ kích thước hàng. (Đó là lý do tại sao đôi khi nhanh hơn một chút để chọn toàn bộ hàng.)

Liên quan:


1
Là 1 byte trên đầu vẫn còn 1 byte trong chỉ mục?
dvtan

1
@dtgq: Một chỉ mục lưu trữ dữ liệu giống như một bảng, vì vậy, có.
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.