Работает ли NChar или Char лучше, чем их альтернативные варианты?
Отличный вопрос. Простой ответ - да в определенных ситуациях. Посмотрим, можно ли это объяснить.
Очевидно, что все мы знаем, что если я создам таблицу со столбцом varchar (255) (назовем этот столбец myColumn) и вставим миллион строк, но поместим только несколько символов в myColumn для каждой строки, таблица будет намного меньше (общее количество страниц данных, необходимых для механизма хранения), чем если бы я создал myColumn как char (255). Каждый раз, когда я выполняю операцию (DML) над этой таблицей и запрашиваю много строк, будет быстрее, когда myColumn varchar, потому что мне не нужно перемещать вокруг всех этих «лишних» пробелов в конце. Перемещение, например, когда SQL Server выполняет внутреннюю сортировку, например, во время отдельной операции или операции объединения, или если он выбирает слияние во время плана запроса и т. Д. Перемещение также может означать время, необходимое для передачи данных с сервера на локальный сервер. компьютер или другой компьютер, или где бы он ни потреблялся.
Но есть некоторые накладные расходы при использовании varchar. SQL Server должен использовать двухбайтовый индикатор (издержки), чтобы в каждой строке узнать, сколько байтов содержится в этой строке myColumn. Проблема не в 2 дополнительных байтах, а в необходимости «декодировать» длину данных в myColumn в каждой строке.
По моему опыту, наиболее целесообразно использовать char вместо varchar в столбцах, к которым будут добавляться запросы. Например, первичный ключ таблицы или другой столбец, который будет проиндексирован. CustomerNumber в демографической таблице, или CodeID в таблице декодирования, или, возможно, OrderNumber в таблице заказов. Используя char, механизм запросов может быстрее выполнить объединение, потому что он может выполнять арифметику с прямым указателем (детерминистически) вместо того, чтобы перемещать свои указатели на переменное количество байтов при чтении страниц. Я знаю, что мог потерять тебя в последнем предложении. Объединения в SQL Server основаны на идее «предикатов». Предикат является условием. Например, myColumn = 1 или OrderNumber <500. </p>
Таким образом, если SQL Server выполняет инструкцию DML, а предикаты или «ключи», к которым присоединяются, имеют фиксированную длину (символ), обработчику запросов не нужно выполнять столько работы, чтобы сопоставить строки из одной таблицы в строки из другой таблицы. Не нужно будет выяснить, как долго находятся данные в строке, а затем пройтись вниз по строке, чтобы найти конец. Все это требует времени.
Теперь имейте в виду, что это может быть плохо реализовано. Я видел char, используемый для полей первичного ключа в онлайн-системах. Ширина должна быть небольшой, то есть char (15) или что-то разумное. И это лучше всего работает в онлайн-системах, потому что вы, как правило, извлекаете или добавляете только небольшое количество строк, поэтому необходимость «тримировать» те конечные пробелы, которые вы получите в наборе результатов, является тривиальной задачей, а не объединением миллионов строк из одной таблицы в миллионы строк в другой таблице.
Еще одна причина, по которой CHAR имеет смысл по сравнению с varchar в онлайн-системах, заключается в том, что он уменьшает разбиение страниц. Используя char, вы, по сути, «резервируете» (и теряете) это пространство, поэтому, если пользователь приходит позже и помещает больше данных в этот столбец, SQL уже выделил для него пространство и он уходит.
Другая причина использования CHAR аналогична второй. Если программист или пользователь выполняет «пакетное» обновление для миллионов строк, например, добавляя какое-то предложение в поле заметки, вы не получите звонка от своего администратора базы данных посреди ночи, задающегося вопросом, почему их накопители заполнены. Другими словами, это приводит к более предсказуемому увеличению размера базы данных.
Таким образом, это 3 способа, которыми онлайновая (OLTP) система может извлечь выгоду из char по сравнению с varchar. Я почти никогда не использую char в сценарии «хранилище / анализ / OLAP», потому что обычно у вас так много данных, что все эти столбцы char могут добавить много потерянного пространства.
Имейте в виду, что 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
Это круто, потому что внутренне мои данные занимают меньше места, потому что они используют varchar. Но когда я использую DTS или SSIS или даже просто вырезал и вставлял из SSMS в Блокнот, я мог использовать представление и получить правильное количество конечных пробелов. В DTS у нас раньше была функция, черт побери, я думаю, что она называлась «предложить столбцы» или что-то в этом роде. В SSIS вы больше не можете этого делать, вам нужно утомительно определять менеджер соединений с плоскими файлами. Но так как у вас есть настроенное представление, SSIS может знать ширину каждого столбца и может сэкономить много времени при построении ваших задач потока данных.
Итак, суть ... используйте varchar. Существует очень небольшое количество причин использовать char, и это только из соображений производительности. Если у вас есть система с сотнями миллионов строк, вы увидите заметную разницу, если предикаты являются детерминированными (char), но для большинства систем использование char просто тратит пространство.
Надеюсь, это поможет.
Джефф