Каковы варианты использования для выбора CHAR над VARCHAR в SQL?

Я понимаю, что CHAR рекомендуется, если все мои значения имеют фиксированную ширину. Но, ну и что? Почему бы просто не выбрать VARCHAR для всех текстовых полей, чтобы быть в безопасности.

Ответ 1

Как правило, выберите CHAR, если все строки будут иметь близкую к одной и той же длине. Выберите VARCHAR, когда длина значительно изменится. CHAR также может быть немного быстрее, потому что все строки имеют одинаковую длину.

Это зависит от реализации БД, но, как правило, VARCHAR использует один или два байта хранения (для длины или завершения) в дополнение к фактическим данным. Итак (при условии, что вы используете однобайтовый набор символов), сохраняя слово "FooBar"

  • CHAR (6) = 6 байтов (без накладных расходов)
  • VARCHAR (10) = 8 байт (2 байта служебных данных)
  • CHAR (10) = 10 байтов (4 байта служебных данных)

Нижняя строка CHAR может быть быстрее и эффективнее для данных относительно одинаковой длины (в пределах разницы длины двух символов).

Примечание. Microsoft SQL имеет 2 байта служебных данных для VARCHAR. Это может варьироваться от БД к БД, но обычно имеется как минимум 1 байт служебных данных, необходимых для указания длины или EOL на VARCHAR.

Как было отмечено Gaven в комментариях, если вы используете многобайтовый символ переменной длины, такой как UTF8, то CHAR хранит максимальное количество байтов, необходимое для хранения количества символов. Поэтому, если для хранения символа UTF8 требуется не более 3 байтов, то CHAR (6) будет зафиксировано в 18 байт, даже если будет хранить только латинские символы. Поэтому в этом случае VARCHAR становится намного лучшим выбором.

Ответ 2

Если вы работаете со мной, и вы работаете с Oracle, я бы, вероятно, заставил вас использовать varchar почти в каждом случае. Предположение, что char использует меньше вычислительной мощности, чем varchar, может быть правдой... на данный момент... но механизмы баз данных со временем становятся лучше, и это общее правило создает будущий "миф".

Другое дело: я никогда не видел проблемы с производительностью, потому что кто-то решил пойти с varchar. Вы будете гораздо лучше использовать свое время для написания хорошего кода (меньше вызовов в базе данных) и эффективного SQL (как работают индексы, как оптимизатор принимает решения, почему exists быстрее, чем in обычно...).

Заключительная мысль: я видел всевозможные проблемы с использованием char, людей, ищущих "когда они должны искать", или людей, ищущих "FOO", когда они должны искать "FOO ( куча пробелов здесь) ', или люди не обрезают конечные пробелы или ошибки с Powerbuilder, добавляя до 2000 бланков значение, которое оно возвращает из процедуры Oracle.

Ответ 3

В дополнение к преимуществам производительности CHAR может использоваться для указания того, что все значения должны иметь одинаковую длину, например столбцы для сокращений состояний в США.

Ответ 4

Данные для хранения: "ABCD"


Char(4) takes 4b

varchar(4) takes 6b

or

Char(40) takes 40b

varchar(40) takes 6b

or

Char(400) takes 400b

varchar(400) takes 6b

Ответ 5

Char немного быстрее, поэтому, если у вас есть столбец, который вы знаете, будет иметь определенную длину, используйте char. Например, сохранение (M) ale/(F) emale/(U) неизвестно для пола или 2 символа для состояния США.

Ответ 6

Поддерживает ли NChar или Char их альтернативы var?

Отличный вопрос. Простой ответ - да в определенных ситуациях. Посмотрим, можно ли это объяснить.

Очевидно, что все мы знаем, что если я создам таблицу с столбцом varchar (255) (позвольте мне вызвать этот столбец myColumn) и вставьте миллион строк, но поместите только несколько символов в myColumn для каждой строки, таблица будет много меньше (общее количество страниц данных, необходимых для механизма хранения), чем если бы я создал myColumn как char (255). Каждый раз, когда я делаю операцию (DML) в этой таблице и запрашиваю много строк, она будет быстрее, когда myColumn будет varchar, потому что мне не нужно перемещать все эти "лишние" пробелы в конце. Перемещение, как в случае, когда SQL Server выполняет внутренние сортировки, например, во время отдельной операции или операции объединения, или если он выбирает слияние во время его плана запроса и т.д. Перемещение также может означать время, необходимое для получения данных с сервера на локальный ПК или на другой компьютер или где бы он ни потреблялся.

Но в использовании varchar есть некоторые накладные расходы. SQL Server должен использовать двухбайтовый индикатор (служебные данные) для каждой строки, чтобы узнать, сколько байтов имеет в нем определенная строка myColumn. Это не дополнительные 2 байта, которые представляют проблему, а необходимость "декодировать" длину данных в моей таблице в каждой строке.

В моих опытах наиболее целесообразно использовать Char вместо varchar для столбцов, к которым будут присоединяться запросы. Например, первичный ключ таблицы или какой-либо другой столбец, который будет проиндексирован. CustomerNumber в демографической таблице или CodeID в таблице декодирования или, возможно, OrderNumber в таблице заказов. Используя char, механизм запросов может быстрее выполнить соединение, потому что он может выполнять арифметику с прямым указателем (детерминированно), а не перемещать ее, указывая переменное количество байтов при чтении страниц. Я знаю, что, возможно, потерял тебя в этом последнем предложении. Соединения в SQL Server основаны на идее "предикатов". Предикат является условием. Например, myColumn = 1 или OrderNumber < 500.

Итак, если SQL Server выполняет оператор DML, а предикаты или "ключи", к которым они присоединены, являются фиксированной длиной (char), механизм запросов не должен выполнять столько работы, чтобы соответствовать строкам из одна таблица к строкам из другой таблицы. Ему не нужно будет выяснять, сколько времени данные находятся в строке, а затем перейти по строке, чтобы найти конец. Все это требует времени.

Теперь имейте в виду, что это может быть легко реализовано плохо. Я видел Char для первичных ключевых полей в онлайн-системах. Ширина должна быть небольшой, т.е. char (15) или что-то разумное. И он лучше всего работает в онлайн-системах, потому что вы обычно извлекаете или увеличиваете небольшое количество строк, поэтому, чтобы "rtrim", эти конечные пробелы, которые вы получите в результирующем наборе, являются тривиальной задачей, а не объединять миллионы строки из одной таблицы в миллионы строк в другой таблице.

Другая причина Char имеет смысл по сравнению с varchar в онлайновых системах, так это то, что она уменьшает разбиение страниц. Используя char, вы по существу "резервируете" (и тратите) это пространство, поэтому, если пользователь приходит позже и помещает больше данных в этот столбец, SQL уже выделил место для него и в нем идет.

Другая причина использования Char аналогична второй причине. Если программист или пользователь выполняет "пакетное" обновление до миллионов строк, добавив некоторое предложение в поле примечания, например, вы не получите звонок от вашего администратора баз данных в середине ночи, задаваясь вопросом, почему их диски заполнены. Другими словами, это приводит к более предсказуемому росту размера базы данных.

Итак, это три способа, которыми система онлайн (OLTP) может извлечь выгоду из Char через varchar. Я почти никогда не использую Char в сценарии хранилища/анализа/OLAP, потому что обычно у вас есть много данных, что все эти столбцы Char могут содержать много потерянного пространства.

Имейте в виду, что Char может сделать вашу базу данных намного больше, но большинство средств резервного копирования имеют сжатие данных, поэтому ваши резервные копии имеют примерно одинаковый размер, как если бы вы использовали varchar. Например, LiteSpeed ​​или RedGate SQL Backup.

Другое использование - в представлениях, созданных для экспорта данных в файл с фиксированной шириной. Скажем, мне нужно экспортировать некоторые данные в плоский файл, который будет читать мейнфрейм. Это фиксированная ширина (не разграничена). Мне нравится хранить данные в моей "промежуточной" таблице как varchar (таким образом, потребляя меньше места в моей базе данных), а затем использовать представление для CAST для всего, что эквивалентно ему Char, с длиной, соответствующей ширине фиксированной ширины для эта колонка. Например:

create table tblStagingTable (
pkID BIGINT (IDENTITY,1,1),
CustomerFirstName varchar(30),
CustomerLastName varchar(30),
CustomerCityStateZip varchar(100),
CustomerCurrentBalance money )

insert into tblStagingTable
(CustomerFirstName,CustomerLastName, CustomerCityStateZip) ('Joe','Blow','123 Main St Washington, MD 12345', 123.45)

create view vwStagingTable AS
SELECT CustomerFirstName = CAST(CustomerFirstName as CHAR(30)),
CustomerLastName = CAST(CustomerLastName as CHAR(30)),
CustomerCityStateZip = CAST(CustomerCityStateZip as CHAR(100)),
CustomerCurrentBalance = CAST(CAST(CustomerCurrentBalance as NUMERIC(9,2)) AS CHAR(10))

SELECT * from vwStagingTable

Это классно, потому что внутренне мои данные занимают меньше места, потому что они используют varchar. Но когда я использую DTS или SSIS или даже просто вырезать и вставлять из SSMS в блокнот, я могу использовать представление и получить нужное количество конечных пробелов. В DTS мы использовали функцию, проклятую, я забыл, я думаю, что она называлась "предлагать колонки" или что-то в этом роде. В SSIS вы больше не можете этого делать, вам нужно утомительно определить диспетчер соединений с плоскими файлами. Но поскольку у вас есть настройка своего представления, SSIS может знать ширину каждого столбца, и он может экономить много времени при построении задач потока данных.

Итак, нижняя строка... используйте varchar. Существует очень мало причин использовать Char и это только по соображениям производительности. Если у вас есть система с hundrends из миллионов строк, вы увидите заметную разницу, если предикаты детерминированы (char), но для большинства систем, использующих Char, просто теряется пространство.

Надеюсь, что это поможет. Джефф

Ответ 7

Есть преимущества производительности, но здесь не упоминается: перемещение строк. С char вы резервируете все пространство заранее. Так что пусть у вас есть char (1000), и вы сохраняете 10 символов, вы будете использовать все 1000 символов пространства. В varchar2 (1000) вы будете использовать только 10 символов. Проблема возникает, когда вы изменяете данные. Скажем, вы обновили столбец, чтобы теперь содержать 900 символов. Возможно, что пространство для расширения varchar недоступно в текущем блоке. В этом случае движок БД должен перенести строку в другой блок и сделать указатель в исходном блоке на новую строку в новом блоке. Чтобы прочитать эти данные, движок БД теперь должен будет прочитать 2 блока.
Никто не может двусмысленно сказать, что варчар или char лучше. Существует пространство для временного компромисса и рассмотрение вопроса о том, будут ли данные обновляться, особенно если есть хороший шанс, что он будет расти.

Ответ 8

Существует разница между ранней оптимизацией производительности и использованием правила правильной практики. Если вы создаете новые таблицы, в которых вы всегда будете иметь поле с фиксированной длиной, имеет смысл использовать CHAR, вы должны использовать его в этом случае. Это не ранняя оптимизация, а реализация эмпирического правила (или лучшей практики).

то есть. - Если у вас есть поле с двумя буквами, используйте CHAR (2). Если у вас есть поле с фактическими именами состояний, используйте VARCHAR.

Ответ 9

Я бы выбрал varchar, если столбец не сохранил фиксированное значение, например, код состояния штата США, который всегда содержит 2 символа, а список действительных кодов штатов США не изменяется часто:).

В любом другом случае, даже если хранить хэшированный пароль (который является фиксированной длиной), я бы выбрал varchar.

Почему столбец типа char всегда выполняется с пробелами, что делает для столбца my_column, который определяется как char (5) со значением "ABC" внутри сравнения:

my_column = 'ABC' -- my_column stores 'ABC  ' value which is different then 'ABC'

ложно.

Эта функция может привести ко многим раздражающим ошибкам во время разработки и сделать тестирование сложнее.

Ответ 10

CHAR занимает меньше места для хранения, чем VARCHAR, если все ваши значения данных в этом поле имеют одинаковую длину. Теперь, возможно, в 2009 году база данных 800 ГБ будет одинаковой для всех целей и задач как 810 ГБ, если вы преобразовали VARCHAR в CHAR, но для коротких строк (1 или 2 символа) CHAR по-прежнему является "лучшей практикой" в отрасли сказать.

Теперь, если вы посмотрите на большое количество типов данных, большинство баз данных предоставляют даже для целых чисел (бит, крошечный, int, bigint), есть причины выбрать один из них. Просто выбор bigint каждый раз на самом деле немного не знает цели и использования поля. Если поле просто представляет возраст людей в годах, bigint является излишним. Теперь это не обязательно "неправильно", но оно неэффективно.

Но его интересный аргумент, и по мере того, как базы данных со временем улучшаются, можно утверждать, что CHAR vs VARCHAR становится менее релевантным.

Ответ 11

Я поддерживаю комментарий Джима МакКета.

Кроме того, индексирование и полное сканирование таблицы быстрее, если в таблице есть только столбцы CHAR. В основном оптимизатор сможет предсказать, насколько велика каждая запись, если она имеет только столбцы CHAR, тогда как для проверки значения размера каждого столбца VARCHAR необходимо проверить.

Кроме того, если вы обновите столбец VARCHAR до размера, большего, чем его предыдущий контент, вы можете заставить базу данных перестроить свои индексы (потому что вы заставили базу данных физически переместить запись на диск). Хотя с столбцами CHAR, которые никогда не произойдут.

Но вам, вероятно, не понравится производительность, если ваша таблица не огромна.

Вспомните мудрые слова Джикстры. Ранняя оптимизация производительности - это корень всего зла.

Ответ 12

Это классическое сочетание пространства и производительности.

В MS SQL 2005 Varchar (или NVarchar для lanuagues, требующих два байта на символ, т.е. китайский), является переменной длиной. Если вы добавите в строку после того, как она была записана на жесткий диск, она будет находить данные в некондиционированном местоположении в исходной строке и привести к фрагментации ваших файлов данных. Это повлияет на производительность.

Итак, если пространство не является проблемой, тогда Char лучше для производительности, но если вы хотите сохранить размер базы данных, тогда лучше использовать varchars.

Ответ 13

Многие люди указали, что если вы знаете, что точная длина значения с использованием CHAR имеет некоторые преимущества. Но при сохранении штатов США как CHAR (2) сегодня здорово, когда вы получаете сообщение от продаж, что "Мы только что сделали нашу первую продажу Австралии", вы находитесь в мире боли. Я всегда присылаю, чтобы переоценить, как долго я думаю, что поля должны быть скорее, чем делать "точные" предположения для покрытия будущих событий. VARCHAR предоставит мне большую гибкость в этой области.

Ответ 14

При вычислении фактического нужного размера для значения столбца и небольшого объема для Varchar существует небольшая часть обработки, поэтому, если вы точно знаете, как долго значение будет всегда, лучше использовать Char и избегайте попадания.

Ответ 15

Я думаю, что в вашем случае, вероятно, нет причин не выбирать Varchar. Это дает вам гибкость и, как уже упоминалось рядом респондентов, производительность такова, что сейчас, за исключением особых обстоятельств, мы, простые смертные (в отличие от Google DBA), не заметили разницы.

Интересная вещь, которая стоит отметить, когда речь заходит о типах БД, это sqlite (популярная мини-база данных с довольно впечатляющей производительностью) помещает все в базу данных в виде строки и типа на лету.

Я всегда использую VarChar и обычно делаю его намного больше, чем мне может понадобиться. Например. 50 для Firstname, как вы говорите, почему бы просто не быть в безопасности.

Ответ 16

фрагментация. Char резервирует пространство, а VarChar - нет. Разделение страницы может потребоваться для обновления в varchar.

Ответ 17

Я бы никогда не использовал символы. У меня была эта дискуссия со многими людьми, и они всегда поднимают усталое клише, что чарс быстрее. Ну, я говорю, насколько быстрее? О чем мы здесь говорим, миллисекундах, секундах и если да, то сколько? Вы говорите мне, потому что кто-то утверждает, что это на несколько миллисекунд быстрее, мы должны ввести в систему тонны трудно исправляемых ошибок?

Итак, вот некоторые проблемы, с которыми вы столкнетесь:

Каждое поле будет дополнено, так что вы всегда будете иметь код, который везде имеет RTRIMS. Это также огромная трата дискового пространства для более длинных полей.

Теперь предположим, что у вас есть типичный пример поля char, состоящего только из одного символа, но поле является необязательным. Если кто-то передает пустую строку в это поле, он становится одним пробелом. Поэтому, когда другое приложение/процесс запрашивает его, они получают один пробел, если они не используют rtrim. У нас были XML-документы, файлы и другие программы, отображающие только один пробел в необязательных полях и разбивающие вещи.

Так что теперь вы должны убедиться, что вы передаете пустые строки, а не пустые, в поле char. Но это НЕ правильное использование нуля. Вот использование нуля. Допустим, вы получили файл от поставщика

Имя | Пол | Город

Боб || Лос-Анджелес

Если пол не указан, введите в таблицу Боба, пустую строку и Лос-Анджелес. Теперь предположим, что вы получили файл и его формат изменился, и пол больше не включен, но был в прошлом.

Имя | Город

Боб | Сиэтл

Ну, теперь, так как пол не включен, я бы использовал нуль. Varchars поддерживают это без проблем.

Чар с другой стороны отличается. Вы всегда должны отправить ноль. Если вы когда-нибудь отправите пустую строку, у вас будет поле с пробелами.

Я мог бы продолжать и исправлять все ошибки, которые мне пришлось исправить с помощью символов и примерно через 20 лет разработки.

Ответ 18

при использовании значений varchar SQL Server нуждается в дополнительных 2 байтах на строку для хранения некоторой информации об этом столбце, тогда как если вы используете char, это не нужно поэтому, если вы

Ответ 19

В некоторых базах данных SQL VARCHAR будет дополняться максимальным размером, чтобы оптимизировать смещения. Это делается для ускорения полных сканирований и индексов таблицы.

Из-за этого у вас нет экономии пространства, используя VARCHAR (200) по сравнению с CHAR (200)

Ответ 20

Использование CHAR (NCHAR) и VARCHAR (NVARCHAR) приводит к различиям в том, как сервер базы данных хранит данные. Первый вводит конечные пробелы; Я столкнулся с проблемой при использовании его с LIKE-оператором в функциях SQL SERVER. Поэтому я должен сделать это безопасным, используя VARCHAR (NVARCHAR) все время.

Например, если у нас есть таблица TEST (ID INT, Status CHAR (1)), и вы пишете функцию для перечисления всех записей с определенным значением, например:

CREATE FUNCTION List(@Status AS CHAR(1) = '')
RETURNS TABLE
AS
RETURN
SELECT * FROM TEST
WHERE Status LIKE '%' + @Status '%'

В этой функции мы ожидаем, что когда мы поместим параметр по умолчанию, функция вернет все строки, но на самом деле это не так. Измените тип данных @Status на VARCHAR, чтобы устранить проблему.