Показники показників для CHAR проти VARCHAR (Postgres)


16

У цій відповіді ( /programming/517579/strings-as-primary-keys-in-sql-database ) одне зауваження потрапило мені в очі:

Також майте на увазі, що часто існує різниця між CHAR і VARCHAR при порівнянні індексів

Чи застосовується це чи все ще застосовується до Postgres?

Я знайшов сторінки в Oracle, які стверджують, що CHARце більш-менш псевдонім для, VARCHARтому продуктивність індексу однакова, але я не знайшов нічого остаточного на Postgres.

Відповіді:


24

CHARі VARCHARреалізуються точно так само в Postgres (і Oracle). Немає різниці в швидкості використання цих типів даних.

Однак є одна відмінність, яка може змінити продуктивність: charстовпець завжди залитий заданою довжиною. Отже, якщо ви визначаєте стовпчик як " char(100)і" як, varchar(100)але зберігають лише 10 символів у кожному, у char(100)колонці використовується 100 символів для кожного значення (10 символів, які ви зберегли, плюс 90 пробілів), тоді як varcharстовпець зберігає лише 10 символів.

Порівнювати 100 символів зі 100 символами буде повільніше, ніж порівнювати 10 символів з 10 символами - хоча я сумніваюся, що ви можете насправді виміряти цю різницю в SQL запиті.

Якщо ви заявляєте обидві довжиною 10 символів і завжди зберігаєте в них рівно 10 символів, то різниці абсолютно немає (це справедливо для Oracle і Postgres)

Тож єдиною відмінністю є прокладка, яка робиться для charтипу даних.


Також майте на увазі, що часто існує різниця між CHAR і VARCHAR при порівнянні індексів

Вищенаведена цитата справедлива лише в тому випадку, якщо (і тільки якщо) charстовпець визначений занадто широким (тобто ви витрачаєте місце через прокладку). Якщо довжина charстовпця завжди використовується повністю (тому не виникає прокладка), то вищенаведена цитата неправильна (принаймні для Postgres та Oracle)


З моєї точки зору, charтип даних насправді не використовує реального слова. Просто використовуйте varchar(або textв Postgres) і забудьте, що charіснує.


2
Порівнювати 100 символів зі 100 символами буде повільніше, ніж порівнювати 10 символів з 10 символами - хоча я сумніваюся, що ви можете насправді виміряти цю різницю в SQL запиті. - Залежно від того, що запит виконує крім сортування, різниця може бути величезною. Ось чому Postgres 9.5 має нову функцію "скорочених ключів": pgeoghegan.blogspot.de/2015/01/…
chirlu

6

Я погоджуюся з усім, що сказано a_horse_with_no_name, і я, як правило, погоджуюся з порадою щодо коментарів Ервіна:

Ні, char є неповноцінним (і застарілим). текст і варчар виконують (майже) те саме.

Метадані

За одним незначним винятком, я використовую єдиний раз char(), коли я хочу, щоб метадані сказали, що ОБОВ'ЯЗКОВО мають мати x символів. Хоча я знаю, що char()скаржиться лише в тому випадку, якщо вхід перевищує ліміт, я часто захищаю від CHECKобмежень внаслідок обмежень. Наприклад,

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

Я роблю це з кількох причин,

  1. char(x)іноді робиться висновок із схемами-навантажувачами як стовпчиком фіксованої ширини. Це може змінити мову, оптимізовану для рядків фіксованої ширини.
  2. Він встановлює конвенцію, яка має сенс і легко виконується. Я можу написати схему-завантажувач мовою, щоб генерувати код із цієї конвенції.

Потрібен приклад, де я можу це зробити,

  1. Двобуквенні абревіатури стану, хоча, оскільки цей список можна перерахувати, я, як правило, роблю це з ENUM.
  2. Ідентифікаційні номери транспортного засобу
  3. Номери моделі (фіксованого розміру)

Про помилки

Зауважте, що деяким людям може бути незручно з невідповідністю повідомлень про помилки з обох боків межі, але це мене не турбує

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)

Контраст с varchar

Більше того, я думаю, що вищенаведена пропозиція дуже добре поєднується з умовами використання, які майже завжди використовуютьсяtext . Ви varchar(n)теж запитуєте . Я ніколи цим не користуюся . Принаймні, я не можу згадати останній раз, коли я користувався varchar(n).

  • Якщо специфікація має поле статичної ширини, якому я довіряю, я використовую char(n),
  • В іншому випадку я використовую textце ефективно varchar(без обмеження)

Якби я знайшов специфікацію, яка мала текстові клавіші змінної довжини, які мали сенс і які я довіряла мати постійну максимальну довжину, я також використала б varchar(n). Однак я не можу придумати нічого, що відповідає цим критеріям.

Додаткові нотатки

Питання та відповіді:


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 не прошив пробілами.


Це просто оптична ілюзія у Postgres. СпробуйтеSELECT pg_column_size(y) FROM x;
дезсо

-2

Я знайшов це найбільш корисним і швидким поясненням у три рядки:

З CHAR (n) VS VARCHAR (N) Vs Текст у постгресах

  • Якщо ви хочете зберегти текст з невідомою довжиною, використовуйте TEXTтип даних.
  • Якщо ви хочете зберегти текст з невідомою довжиною, але ви знаєте максимальну довжину, використовуйте VARCHAR(n).
  • Якщо ви хочете зберегти текст із відомою точною довжиною, використовуйте CHAR(N).
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.