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

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

Обычно выбирайте 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 становится намного лучшим выбором.

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

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

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

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

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

NChar или Char работают лучше, чем их альтернативы var?

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

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

Но есть некоторые накладные расходы при использовании varchar. SQL Server должен использовать двухбайтовый индикатор (служебные данные) для каждой строки, чтобы узнать, сколько байтов в моей колонке этой конкретной строки. Это не лишние 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 over varchar. Я почти никогда не использую char в сценарии склада / анализа / OLAP, потому что обычно у вас есть много данных, которые все эти столбцы столбцов могут добавить к большому количеству потраченного впустую пространства.

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

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

 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 

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

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

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

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

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

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

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

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

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

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

ложный.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Фрагментация. Char оставляет пространство, а VarChar – нет. Для разделения обновлений на varchar может потребоваться разделение страниц.

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

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

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

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

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

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

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

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

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

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

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

Имя | Пол | Город Боб || Лос-Анджелес

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

Имя | Город Боб | Сиэтл

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

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

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

  • t-sql получить все даты между двумя датами
  • Как обновить колонку Identity в SQL Server?
  • T-SQL CASE: как указать WHEN NULL
  • Параметр Pass Array в SqlCommand
  • Как конвертировать секунды в HH: MM: SS с использованием T-SQL
  • Как преобразовать строку dd / mm / yyyy в datetime в SQL Server?
  • Как использовать необязательные параметры в хранимой процедуре T-SQL?
  • Разделительная строка T-SQL
  • Использование StringWriter для сериализации XML
  • Создание таблицы HTML с SQL FOR XML
  • Создайте дату с дневного месяца и года с помощью T-SQL
  • Interesting Posts
    Давайте будем гением компьютера.