PostgreSQL: разница между текстом и varchar (различается символ) - PullRequest
530 голосов
/ 31 января 2011

В чем разница между типом данных text и типами данных character varying (varchar)?

Согласно документации

Если используется символьная переменная без спецификатора длины, тип принимает строки любого размера.Последнее является расширением PostgreSQL.

и

Кроме того, PostgreSQL предоставляет тип текста, в котором хранятся строки любой длины.Хотя текст типа не входит в стандарт SQL, он есть и в некоторых других системах управления базами данных SQL.

Так в чем же разница?

Ответы [ 8 ]

632 голосов
/ 31 января 2011

Нет никакой разницы, под капотом все это varlena ( массив переменной длины ).

Проверьте эту статью в Depesz: http://www.depesz.com/index.php/2010/03/02/charx-vs-varcharx-vs-varchar-vs-text/

Aпара основных моментов:

Суммируя все это:

  • char (n) - занимает слишком много места при работе со значениями короче n (добавляет их кn), и может привести к незначительным ошибкам из-за добавления конечных пробелов, плюс изменение предела проблематично
  • varchar (n) - изменить ограничение в реальной среде (требуется исключительная блокировка, покаизменяющаяся таблица)
  • varchar - как текст
  • текст - для меня победитель - над (n) типами данных, потому что у них нет проблем, и над varchar - потому чтоу него есть отдельное имя

В статье проводится подробное тестирование, чтобы показать, что производительность операций вставки и выбора для всех 4 типов данных одинакова.Также подробно рассматриваются альтернативные способы ограничения длины при необходимости.Ограничения или домены, основанные на функциях, обеспечивают преимущество мгновенного увеличения ограничения длины, и на основании того, что уменьшение ограничения длины строки встречается редко, Депес приходит к выводу, что один из них обычно является лучшим выбором для ограничения длины.

104 голосов
/ 01 февраля 2011

Как указано в документации " Типы символов ", varchar(n), char(n) и text сохраняются одинаково.Единственное отличие состоит в том, что для проверки длины, если она задана, необходимы дополнительные циклы, а также дополнительное пространство и время, если для заполнения требуется char(n).

Однако, когда вам нужно сохранить толькосимвол, есть небольшое преимущество в производительности при использовании специального типа "char" (оставьте двойные кавычки - они являются частью имени типа).Вы получаете более быстрый доступ к полю, и нет никаких затрат на сохранение длины.

Я только что создал таблицу из 1 000 000 случайных чисел "char", выбранных из строчного алфавита.Запрос для получения частотного распределения (select count(*), field ... group by field) занимает около 650 миллисекунд против 760 для тех же данных с использованием поля text.

44 голосов
/ 23 апреля 2016

ОБНОВЛЕНИЕ ЭТАЛОНОВ НА 2016 ГОД (стр.9.5 +)

И с использованием тестов "чистый SQL" (без какого-либо внешнего скрипта)

  1. использовать любой string_generator с UTF8

  2. основные ориентиры:

    2,1. ВСТАВИТЬ

    2,2. ВЫБЕРИТЕ сравнение и подсчет


CREATE FUNCTION string_generator(int DEFAULT 20,int DEFAULT 10) RETURNS text AS $f$
  SELECT array_to_string( array_agg(
    substring(md5(random()::text),1,$1)||chr( 9824 + (random()*10)::int )
  ), ' ' ) as s
  FROM generate_series(1, $2) i(x);
$f$ LANGUAGE SQL IMMUTABLE;

Подготовка конкретного теста (примеры)

DROP TABLE IF EXISTS test;
-- CREATE TABLE test ( f varchar(500));
-- CREATE TABLE test ( f text); 
CREATE TABLE test ( f text  CHECK(char_length(f)<=500) );

Выполнить базовый тест:

INSERT INTO test  
   SELECT string_generator(20+(random()*(i%11))::int)
   FROM generate_series(1, 99000) t(i);

и другие тесты

CREATE INDEX q on test (f);

SELECT count(*) FROM (
  SELECT substring(f,1,1) || f FROM test WHERE f<'a0' ORDER BY 1 LIMIT 80000
) t;

... и использовать EXPLAIN ANALYZE.

ОБНОВЛЕНО СНОВА 2018 (pg10)

немного изменить, чтобы добавить результаты 2018 года и усилить рекомендации.


Результаты за 2016 и 2018 годы

Мои результаты, в среднем, на многих машинах и во многих тестах: все равно
(статистически меньше стандартного отклонения).

Рекомендация

  • Используйте text тип данных,
    избегайте старых varchar(x), потому что иногда это не стандарт, например. в CREATE FUNCTION пунктах varchar(x)varchar(y).

  • Экспресс-лимиты (с такой же varchar производительностью!) С помощью CHECK предложения в CREATE TABLE
    , например. CHECK(char_length(x)<=10).
    При незначительной потере производительности в INSERT / UPDATE вы также можете управлять диапазонами и структурой строк
    , например. CHECK(char_length(x)>5 AND char_length(x)<=20 AND x LIKE 'Hello%')

29 голосов
/ 05 ноября 2015

Руководство по PostgreSQL

Между этими тремя типами нет разницы в производительности, за исключением увеличения места для хранения при использовании типа с пробелом и нескольких дополнительных циклов ЦП для проверки длины при сохранении в столбце с ограниченной длиной. Хотя символ (n) имеет преимущества в производительности в некоторых других системах баз данных, в PostgreSQL такого преимущества нет; на самом деле символ (n) обычно самый медленный из трех из-за дополнительных затрат на хранение. В большинстве случаев вместо текста следует использовать изменяющийся текст или символ.

Я обычно использую текст

Рекомендации: http://www.postgresql.org/docs/current/static/datatype-character.html

15 голосов
/ 11 апреля 2018

На мой взгляд, varchar(n) имеет свои преимущества.Да, они все используют один и тот же базовый тип и все такое.Но следует отметить, что индексы в PostgreSQL имеют ограничение размера 2712 байт на строку.

TL; DR: Если вы используете text type без ограничения и имеете индексы для этих столбцов, вполне возможно, что вы достигнете этого предела для некоторыхваших столбцов и получить сообщение об ошибке при попытке вставить данные, но с помощью varchar(n) вы можете предотвратить это.

Некоторые дополнительные сведения: Проблема в том, что PostgreSQL не даетлюбые исключения при создании индексов для типа text или varchar(n), где n больше 2712. Однако при вставке записи со сжатым размером более 2712 произойдет ошибка.Это означает, что вы можете вставить 100 000 символов строки, которая легко состоит из повторяющихся символов, потому что она будет сжата намного ниже 2712, но вы не сможете вставить строку из 4000 символов, поскольку сжатый размер больше 2712 байт.Используя varchar(n), где n не слишком много больше 2712, вы защищены от этих ошибок.

14 голосов
/ 11 января 2018

text и varchar имеют разные неявные преобразования типов.Самое большое влияние, которое я заметил, это обработка конечных пробелов.Например ...

select ' '::char = ' '::varchar, ' '::char = ' '::text, ' '::varchar = ' '::text

возвращает true, false, true, а не true, true, true, как вы могли ожидать.

4 голосов
/ 24 марта 2017

В некоторой степени ОТ: Если вы используете Rails, стандартное форматирование веб-страниц может отличаться. Для ввода данных формы text можно прокручивать, а поля character varying (Rails string) - однострочные. Показывать представления столько, сколько нужно.

0 голосов
/ 14 марта 2018

character varying(n), varchar(n) - (оба одинаковые).значение будет усечено до n символов без возникновения ошибки.

character(n), char(n) - (оба одинаковые).фиксированной длины и будет дополняться пробелами до конца длины.

text - Неограниченная длина.

Пример:

Table test:
   a character(7)
   b varchar(7)

insert "ok    " to a
insert "ok    " to b

Получаем результаты:

a        | (a)char_length | b     | (b)char_length
----------+----------------+-------+----------------
"ok     "| 7              | "ok"  | 2
...