Типы данных SQL Server для хранения строк и занимают меньше места

У меня есть вопрос относительно типов данных, доступных на языке SQL для хранения данных в самой базе данных. Поскольку я имею дело с довольно большой базой данных, которая имеет тенденцию увеличиваться более чем на 150 ГБ данных, мне нужно уделять пристальное внимание и экономить каждый бит места на жестком диске сервера, чтобы база данных не занимала все драгоценное пространство. Итак, мой вопрос заключается в следующем:

  1. Какой тип данных лучше всего подходит для хранения строки длиной 80-200 символов в базе данных?

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

  3. Существуют ли какие-либо другие методы, которые я мог бы использовать для экономии места в базе данных, чтобы она не расширялась быстро?

Может ли кто-нибудь помочь мне с этим?

P.S. Ребят, у меня тоже 4 вопрос:

  1. Если, например, у меня есть тип данных nvarchar(max), который находится в таблице, а введенная запись занимает всего 100 символов, сколько данных зарезервировано для такого типа записи?

  2. Допустим, у меня есть идентификатор, который имеет следующую форму: 191697193441... Было бы разумнее хранить этот номер как varchar(200) или bigint?


person User987    schedule 13.02.2018    source источник
comment
VARCHAR занимает 1 байт на символ - NVARCHAR требуется 2 байта на символ. Столбец nvarchar(max), содержащий 100 символов, будет использовать 200 байтов (плюс небольшие накладные расходы на строку).   -  person marc_s    schedule 13.02.2018
comment
@marc_s отличное спасибо за это =) А как насчет других типов данных? Существуют ли другие типы данных, которые занимали бы меньше места?   -  person User987    schedule 13.02.2018
comment
@marc_s, вы можете увидеть мой обновленный вопрос? Я разместил 4-й вопрос :)   -  person User987    schedule 13.02.2018
comment
nvarchar и varchar используют 2 и 1 байт для каждого символа соответственно. Если вашему столбцу не нужно хранить символы Юникода, тогда varchar будет правильным выбором, так как он вдвое меньше. Также важно создать столбец с соответствующим типом данных. Если у вас есть столбец, в котором всегда будет до 10 символов, но вы объявляете его как varchar(100), вы потратили 90 символов впустую. Точно так же, если у вас есть поле, в котором будут храниться только числа от 1 до 100, используйте tinyint.   -  person Larnu    schedule 13.02.2018
comment
Для простых строк - нет - в основном это два варианта. Если у вас есть XML, сохраните его как тип данных XML, так как этот тип использует оптимизированный механизм хранения. В общем: если что-то не на самом деле является строкой (числом, датой), не сохраняйте это как строку — используйте наиболее подходящие типы данных (они обычно занимают меньше памяти, чем просто струны)   -  person marc_s    schedule 13.02.2018
comment
@marc_s да да, хороший момент, я буду уделять этому очень пристальное внимание =) ... Итак, в основном, если что-то nvarchar (max) и сохраненные данные nvarchar (100), скажем, сколько места тогда теряется?   -  person User987    schedule 13.02.2018
comment
Типы (n)varchar не будут тратить впустую место — они хранят только то, что вы действительно в них вставляете. Если у вас есть nvarchar(max) (который содержит до 2 ГБ данных!), но вы помещаете в него 100 символов, он использует 200 байтов (+ накладные расходы). Если вы храните в нем только 5 символов, он использует 10 байт (+ накладные расходы)   -  person marc_s    schedule 13.02.2018
comment
@marc_s это довольно интересно. Итак, скажем, у меня есть 1 миллион записей в таблице, хранение nvarchar(80) займет 160 байт, верно? и если бы я использовал varchar (80), я бы действительно сэкономил 80 МБ места, верно?   -  person User987    schedule 13.02.2018
comment
Да, точно. Итак, мой вывод: используйте nvarchar только, если вам действительно нужна поддержка таких вещей, как Unicode-алфавиты — иврит, кириллица, арабский, дальневосточный и т. д. — в противном случае соглашайтесь на varchar   -  person marc_s    schedule 13.02.2018
comment
@marc_s отлично отмечу это как самое главное. О, и кстати. У меня есть еще один вопрос, я обновлю свой первоначальный вопрос =)   -  person User987    schedule 13.02.2018
comment
@marc_s Я обновил свой первоначальный вопрос пятым. Имеет ли смысл хранить число 191697193441 как varchar(200) или bigint в базе данных?   -  person User987    schedule 13.02.2018
comment
@ User987: Конечно, вы должны использовать целые типы для целых значений!   -  person Stefan M    schedule 13.02.2018


Ответы (2)


Размер, необходимый для nvarchar, составляет 2 байта на символ, так как он представляет данные Unicode. varchar требуется 1 байт на символ. Размер хранилища равен фактическому количеству введенных символов + 2 байта служебных данных. Это также верно для varchar(max).

Из https://docs.microsoft.com/en-us/sql/t-sql/data-types/char-and-varchar-transact-sql:

varchar [ ( n | max ) ] Строковые данные переменной длины, отличные от Unicode. n определяет длину строки и может принимать значения от 1 до 8000. max указывает, что максимальный размер хранилища составляет 2^31-1 байт (2 ГБ). Размер хранилища равен фактической длине введенных данных + 2 байта.

Итак, для вашего 4-го вопроса nvarchar потребуется 100 * 2 + 2 = 202 байта, varchar потребуется 100 * 1 + 2 = 102 байта.

person Stefan M    schedule 13.02.2018

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

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

Итак, мое общее эмпирическое правило: делайте их настолько большими, насколько того требуют бизнес-требования, но не больше. Тривиально изменить размеры переменных данных на большую длину в будущем, если требования изменятся.

person Muthukumaresan T    schedule 13.02.2018
comment
Изменение размера не является тривиальным. А современные базы данных, такие как Microsoft Azure SQL, даже не позволяют выбрать что-либо меньшее, чем varchar(max), так как это не даст никакого преимущества. - person Stefan M; 13.02.2018
comment
@StefanM: по крайней мере, для SQL Server, определенно имеет смысл использовать правильную длину, а не только (n)varchar(max) для всего ! - person marc_s; 13.02.2018
comment
Интересный сайт, спасибо за ссылку. Кажется, это тест на скорость, а не на размер (что в данном случае не имеет значения). Так что да, если данный размер известен, то, безусловно, правильно выбрать этот размер для (n) varchar. Он по-прежнему недоступен в базах данных Microsoft Azure SQL. ;) - person Stefan M; 13.02.2018