Я розумію, що CHAR рекомендується, якщо всі мої значення мають фіксовану ширину. Але, так що? Чому б просто не вибрати VARCHAR для всіх текстових полів, щоб бути безпечним.
Я розумію, що CHAR рекомендується, якщо всі мої значення мають фіксовану ширину. Але, так що? Чому б просто не вибрати VARCHAR для всіх текстових полів, щоб бути безпечним.
Відповіді:
Як правило, виберіть CHAR, якщо всі ряди матимуть однакову довжину . Виберіть VARCHAR, коли довжина значно змінюється . CHAR також може бути трохи швидшим, оскільки всі ряди однакової довжини.
Він змінюється залежно від реалізації БД, але зазвичай VARCHAR використовує один чи два байти зберігання (для тривалості чи припинення) на додаток до фактичних даних. Отже (припускаючи, що ви використовуєте однобайтовий набір символів), зберігаючи слово "FooBar"
Підсумковий рядок CHAR може бути швидшим та більш ефективним для простору для даних відносно однакової довжини (в межах різниці в довжині двох символів).
Примітка : Microsoft SQL має 2 байти накладних витрат для VARCHAR. Це може відрізнятися від БД до БД, але, як правило, є щонайменше 1 байт накладних витрат, необхідний для позначення довжини або EOL на VARCHAR.
Як вказував Гевен у коментарях, якщо ви використовуєте багатобайтовий набір символів змінної довжини типу UTF8, то CHAR зберігає максимальну кількість байтів, необхідну для зберігання кількості символів. Отже, якщо для зберігання символу UTF8 потрібно щонайменше 3 байти, то CHAR (6) буде зафіксовано на 18 байт, навіть якщо зберігається лише символ lat1. Тож у цьому випадку VARCHAR стає набагато кращим вибором.
Якщо ви працюєте зі мною, а ви працюєте з Oracle, я, мабуть, змусив би вас використовувати varchar
майже за будь-яких обставин. Припущення, що char
використовує меншу потужність обробки, ніж varchar
може бути правдою ... поки що ... але двигуни бази даних з часом стають кращими, і таке загальне правило має форму майбутнього "міфу".
Інша річ: я ніколи не бачив проблем із виконанням, тому що хтось вирішив піти varchar
. Ви набагато краще використаєте свій час написання хорошого коду (менше дзвінків до бази даних) та ефективного SQL (як працюють індекси, як оптимізатор приймає рішення, чому exists
швидше, ніж in
зазвичай ...).
Заключна думка: я бачив всілякі проблеми з використанням CHAR
, люди, які шукають "", коли вони повинні шукати ", або люди, які шукають" FOO ", коли вони повинні шукати" FOO (куча пробілів тут) ". або люди, які не обрізають пробіли, або помилки, що Powerbuilder додає до 2000 заготовок до значення, яке воно повертає в рамках процедури Oracle.
Окрім переваг від продуктивності, CHAR
можна використовувати, щоб вказати, що всі значення повинні бути однакової довжини, наприклад, стовпець для скорочень штатів США.
CHAR
, вам доведеться переконатися, що ваші знижки знижуються.
Char є трохи швидшим, тому якщо у вас стовпець, який ви знаєте, буде певної довжини, використовуйте char. Наприклад, зберігання (M) ale / (F) emale / (U) nknown для статі або 2 символи для штату США.
Чи краще NChar чи Char краще, ніж їх альтернативи?
Чудове запитання. Проста відповідь - так у певних ситуаціях. Подивимось, чи можна це пояснити.
Очевидно, всі ми знаємо, що якщо я створять таблицю зі стовпцем varchar (255) (назвемо цей стовпець myColumn) і вставляю мільйон рядків, але вкладаю лише кілька символів у myColumn для кожного рядка, таблиця буде набагато меншою (загальна кількість сторінок даних, необхідних механізму зберігання даних), ніж якби я створив myColumn як char (255). Щоразу, коли я виконую операцію (DML) над цією таблицею і запитую багато рядків, це буде швидше, коли myColumn варчар, тому що мені не потрібно рухатись усі ці "зайві" пробіли в кінці. Перемістіться, як у випадку, коли SQL Server робить внутрішні сорти, такі як під час окремої операції або об'єднання, або якщо він обирає злиття під час плану запитів тощо.
Але в роботі із варчаром є деякі накладні витрати. SQL Server повинен використовувати двобайтовий індикатор (накладні витрати), щоб у кожному рядку знати, скільки байтів має мій стовпець конкретного рядка в ньому. Не зайві 2 байти представляють проблему, це необхідність "розшифровувати" довжину даних у myColumn у кожному рядку.
На мій досвід, найбільш сенс використовувати 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 схожа на другу причину. Якщо програміст або користувач зробить "пакетне" оновлення на мільйони рядків, додавши, наприклад, якесь речення до поля примітки, ви не отримаєте дзвінок від своєї DBA посеред ночі, цікаво, чому їх накопичувачі заповнені. Іншими словами, це призводить до більш передбачуваного зростання розміру бази даних.
Отже, це 3 способи, коли онлайн-система (OLTP) може отримати вигоду від чарівності. Я майже ніколи не використовую char у складі / аналізі / сценарії OLAP, тому що зазвичай у вас є так багато даних, що всі ці стовпчики char можуть скласти багато витраченого місця.
Майте на увазі, що char може зробити вашу базу даних значно більшою, але більшість інструментів резервного копіювання мають стиснення даних, тому ваші резервні копії, як правило, приблизно такого ж розміру, як якщо б ви використовували varchar. Наприклад, резервне копіювання LiteSpeed або RedGate SQL.
Ще одне використання - у представленнях, створених для експорту даних у файл із фіксованою шириною. Скажімо, я маю експортувати деякі дані в плоский файл, щоб прочитати мейнфрейм. Це фіксована ширина (не обмежена). Мені подобається зберігати дані в моїй таблиці "постановки" як varchar (таким чином, в моїй базі даних витрачається менше місця), а потім використовувати вигляд, щоб КАСТИТИ все, що є еквівалентним, при цьому довжина відповідає ширині фіксованої ширини для цього стовпця . Наприклад:
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 може знати ширину кожного стовпця, і це може заощадити багато часу при складанні завдань по потоку даних.
Отже, підсумок ... використовуйте варчар. Існує дуже мала кількість причин використовувати char, і це лише з міркувань продуктивності. Якщо у вас є система з тисячами мільйонів рядків, ви побачите помітну різницю, якщо предикати детерміновані (char), але для більшості систем, які використовують char, це просто витрачає місце.
Сподіваюся, що це допомагає. Джефф
Переваги від продуктивності є, але ось такий, про який не було сказано: міграція рядків. За допомогою char ви заздалегідь резервуєте весь простір. Отже, скажімо, у вас є char (1000), і ви зберігаєте 10 символів, ви будете використовувати всі 1000 символів місця. У varchar2 (1000) ви будете використовувати лише 10 символів. Проблема виникає, коли ви змінюєте дані. Скажімо, ви оновлюєте стовпець, який тепер містить 900 символів. Можливо, що в поточному блоці місця для розширення варшара немає. У цьому випадку двигун БД повинен перемістити рядок до іншого блоку та зробити вказівник у вихідному блоці на новий рядок у новому блоці. Щоб прочитати ці дані, двигун БД тепер повинен буде прочитати 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 році база даних 800 ГБ однакова для всіх намірів і цілей, як 810 ГБ, якщо ви перетворили VARCHAR на CHAR, але для коротких рядків (1 або 2 символи), я б сказав, CHAR все ще є найкращою практикою в галузі.
Тепер якщо ви подивитесь на різноманітність типів даних, що більшість баз даних забезпечують навіть цілі числа (біт, tiny, int, bigint), то є причини, щоб вибрати одне за іншим. Просто вибираючи bigint кожен раз, насправді трохи не знаючи цілей та використання цього поля. Якщо поле просто представляє вік людей у роках, біґіт є надмірним. Тепер це не обов'язково "неправильно", але це не ефективно.
Але це цікавий аргумент, і оскільки бази даних з часом вдосконалюються, можна стверджувати, що CHAR vs VARCHAR стає менш актуальним.
Я стою за коментарем Джима Маккіта.
Крім того, індексація та сканування повної таблиці швидше, якщо у вашій таблиці є лише стовпці CHAR. В основному оптимізатор зможе передбачити, наскільки велика кожна запис, якщо вона містить лише стовпці CHAR, тоді як їй потрібно перевірити значення розміру кожного стовпця VARCHAR.
Крім того, якщо ви оновите стовпчик VARCHAR на розмір, більший за його попередній вміст, ви можете змусити базу даних відновити свої індекси (тому що ви змусили базу даних фізично перемістити запис на диску). Хоча зі стовпцями CHAR, які ніколи не трапляться.
Але ви, мабуть, не будете дбати про показник ефективності, якщо ваш стіл величезний.
Згадайте мудрі слова Джикстра. Рання оптимізація продуктивності є коренем усього зла.
CHAR
стовпець, індекси також потрібно оновлювати. У цьому відношенні немає різниці в оновленні стовпця VARCHAR або CHAR. Подумайте про оновлення FOO
до BAR
.
Багато людей зазначають, що якщо ви знаєте точну довжину значення за допомогою CHAR, є деякі переваги. Але хоч зберігати штати США як CHAR (2) чудово сьогодні, коли ви отримуєте повідомлення від продажів, що "Ми щойно здійснили перший продаж в Австралію", ви перебуваєте у світі болю. Я завжди надсилаю переоцінювати, як довго, на мою думку, знадобиться поля, а не робити «точну» здогадку, щоб висвітлити майбутні події. VARCHAR надасть мені більшої гнучкості в цій галузі.
Я думаю, що у вашому випадку, мабуть, немає причин не вибирати Варчара. Це дає вам гнучкість, і, як вже зазначалося в ряді респондентів, продуктивність зараз така, що, за винятком дуже специфічних обставин, ми загиблих смертних (на відміну від Google DBA) не помітять різниці.
Цікава річ, яку варто зауважити, коли мова заходить про типи БД - це sqlite (популярна міні-база даних з досить вражаючою продуктивністю), що вміщує все в базу даних як рядок і типи на ходу.
Я завжди використовую VarChar і зазвичай роблю його набагато більшим, ніж я можу вкрай потребувати. Напр. 50 для Імені, як ви кажете, чому б не просто бути в безпеці.
Я б ніколи не використовував символів. Я мав цю дискусію з багатьма людьми, і вони завжди виховують набридне кліше, що чарівність швидша. Ну я кажу, наскільки швидше? Про що ми говоримо тут, мілісекунди, секунди і якщо так, то скільки? Ви мені говорите, оскільки хтось стверджує, що це на кілька мілісекунд швидше, ми повинні ввести багато тонких помилок, щоб виправити помилки в системі?
Ось ось деякі проблеми, з якими ви зіткнетесь:
Кожне поле буде заповнено, тому ви назавжди отримаєте код, який скрізь має RTRIMS. Це також величезна витрата дискового простору на довші поля.
Тепер скажімо, що у вас є найважливіший приклад знаку поля лише одного символу, але поле необов’язкове. Якщо хтось передає порожнє рядок до цього поля, він стає одним пробілом. Отже, коли інша програма / процес запитує її, вони отримують один єдиний простір, якщо вони не використовують rtrim. У нас були XML документи, файли та інші програми, відображали лише один пробіл, у необов’язкових полях та розбивали речі.
Отже, тепер ви повинні переконатися, що ви передаєте нулі, а не порожню рядок, до поля char. Але це НЕ правильне використання нуля. Ось використання нуля. Скажімо, ви отримуєте файл від постачальника
Назва | Стать | Місто
Боб || Лос-Анджелес
Якщо стать не вказаний, ніж ви введете Боб, порожню рядок та Лос-Анджелес в таблицю. Тепер скажемо, що ви отримуєте файл, його формат змінюється, і стать вже не включається, але це було раніше.
Назва | Місто
Боб | Сіетл
Ну а оскільки гендер не включений, я би використовував null. Варчари підтримують це без проблем.
Чар з іншого боку, інший. Ви завжди повинні надсилати null. Якщо ви коли-небудь надішлете порожній рядок, ви отримаєте поле, в якому є пробіли.
Я міг би продовжувати роботу з усіма помилками, які мені доводилося виправляти через показники та приблизно за 20 років розвитку.
Існує кілька невеликих накладних витрат для обчислення фактичного необхідного розміру для значення стовпця та виділення місця для Varchar, тому, якщо ви точно впевнені, як довго це значення буде завжди, краще використовувати Char і уникати попадання.
Це класичний простір порівняно з продуктивністю.
У MS SQL 2005 Varchar (або NVarchar для лануагів, які потребують двох байтів на символ, тобто китайська), мають різну довжину. Якщо ви додасте до рядка після того, як він був записаний на жорсткий диск, він знайде дані в непомітному місці до вихідного рядка і призведе до фрагментації ваших файлів даних. Це вплине на продуктивність.
Отже, якщо простір не є проблемою, то Char краще для продуктивності, але якщо ви хочете зменшити розмір бази даних, то варшари краще.
Фрагментація. Чар зарезервує простір, а VarChar ні. Розділення сторінок може знадобитися для оновлення до varchar.
CHAR
стовпця може статися розкол сторінки .
У деяких базах даних SQL VARCHAR буде викладений на максимальний розмір, щоб оптимізувати компенсації. Це для прискорення сканування повних таблиць та індексів.
Через це у вас немає економії місця за допомогою VARCHAR (200) порівняно з CHAR (200)
Використання CHAR (NCHAR) та VARCHAR (NVARCHAR) приносить відмінності в способах зберігання даних сервером баз даних. Перший вводить пробіли; Я зіткнувся з проблемою при використанні його з оператором LIKE у функціях SQL SERVER. Тому я маю зробити це безпечним, використовуючи VARCHAR (NVARCHAR) весь час.
Наприклад, якщо у нас є таблиця TEST (ID INT, статус CHAR (1)) , і ви пишете функцію, щоб перелічити всі записи з певним значенням, наприклад наступні:
CREATE FUNCTION List(@Status AS CHAR(1) = '')
RETURNS TABLE
AS
RETURN
SELECT * FROM TEST
WHERE Status LIKE '%' + @Status '%'
У цій функції ми очікуємо, що коли ми поставимо параметр за замовчуванням, функція поверне всі рядки, але насправді це не так. Змінення типу даних @Status на VARCHAR вирішить проблему.