NodeJS Back-end Инженер

NodeJS Back-end Инженер

Роадмап навыков для прокачки

Зачем нужно много типов INT, почему нельзя использовать один тип?

DatabasesSQLTypes

Основная идея

Разные типы INT (TINYINT, SMALLINT, INT, BIGINT) существуют для оптимизации хранения данных — каждый тип занимает разное количество байт и поддерживает разный диапазон значений, что позволяет экономить дисковое пространство и память.

Ключевые аспекты

  • Размер хранения — TINYINT занимает 1 байт, INT — 4 байта, BIGINT — 8 байт
  • Диапазон значений — чем больше размер, тем больший диапазон чисел можно хранить
  • Производительность — меньшие типы быстрее обрабатываются и занимают меньше места в индексах
  • Экономия ресурсов — в таблице с миллионами записей разница в размере существенна

Плюсы правильного выбора типа

  • Экономия дискового пространства (особенно важно для больших таблиц)
  • Более эффективное использование кэша базы данных
  • Быстрее работа с индексами
  • Меньшее потребление оперативной памяти

Минусы использования только больших типов

  • Избыточный расход места: статус 0/1 в BIGINT — это 8 байт вместо 1
  • Замедление запросов при работе с большими объёмами данных
  • Неэффективное использование ресурсов сервера

Частые ошибки на собеседованиях

  • Считают, что разницы в производительности нет — на больших таблицах она значительная
  • Забывают про ограничения диапазона — переполнение TINYINT при значении > 127 (signed)
  • Не учитывают unsigned — диапазон удваивается для положительных чисел
  • Используют BIGINT везде "на всякий случай" — это плохая практика

Введение и проблематика

При проектировании базы данных выбор правильного типа данных — одно из ключевых решений. Может показаться, что проще использовать один универсальный целочисленный тип для всех случаев, но на практике это приводит к серьёзным проблемам с производительностью и хранением.

В таблице с 10 миллионами записей замена BIGINT на TINYINT для одной колонки экономит около 70 МБ дискового пространства.

Почему это важно?

База данных работает с дисковым пространством и оперативной памятью. Чем меньше места занимают данные:

  • Тем больше записей помещается в кэш
  • Тем быстрее читаются данные с диска
  • Тем эффективнее работают индексы
  • Тем меньше стоимость хранения

Базовая теория

Типы целых чисел в SQL

ТипРазмерДиапазон (signed)Диапазон (unsigned)
TINYINT1 байт-128 до 1270 до 255
SMALLINT2 байта-32 768 до 32 7670 до 65 535
MEDIUMINT3 байта-8 388 608 до 8 388 6070 до 16 777 215
INT4 байта-2 147 483 648 до 2 147 483 6470 до 4 294 967 295
BIGINT8 байт-9.2 × 10¹⁸ до 9.2 × 10¹⁸0 до 1.8 × 10¹⁹
⚠️

MEDIUMINT (3 байта) поддерживается не во всех СУБД. В PostgreSQL его нет, используется SMALLINT или INT.

Визуализация размеров

graph LR A[TINYINT<br/>1 байт] --> B[SMALLINT<br/>2 байта] B --> C[INT<br/>4 байта] C --> D[BIGINT<br/>8 байт]

Практические примеры

Выбор типа для разных сценариев

sql
-- Возраст: 0-150 лет
-- Используем TINYINT UNSIGNED (0-255)
CREATE TABLE users (
    id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(100),
    age TINYINT UNSIGNED  -- 1 байт, достаточно для возраста
);

Сравнение размера таблиц

sql
-- Таблица со статусами (0/1/2)
-- Плохо: используем INT
CREATE TABLE orders_bad (
    id INT PRIMARY KEY,
    status INT  -- 4 байта на статус 0/1/2
);
 
-- Хорошо: используем TINYINT
CREATE TABLE orders_good (
    id INT PRIMARY KEY,
    status TINYINT  -- 1 байт на статус 0/1/2
);
 
-- При 10 млн записей:
-- orders_bad.status: 10 000 000 × 4 = 40 МБ
-- orders_good.status: 10 000 000 × 1 = 10 МБ
-- Экономия: 30 МБ только на одной колонке!

Влияние на производительность

Размер индексов

Индексы хранят копии значений колонок. Меньший тип = меньший индекс = быстрее поиск.

sql
-- Индекс на INT (4 байта) vs TINYINT (1 байт)
-- При 1 млн записей:
-- INT индекс: ~4 МБ
-- TINYINT индекс: ~1 МБ
 
CREATE INDEX idx_status ON orders(status);

Кэширование

База данных кэширует часто используемые данные в RAM. Меньшие типы = больше данных в кэше = меньше обращений к диску.

graph TD A[Запрос данных] --> B{Данные в кэше?} B -->|Да| C[Быстрый ответ из RAM] B -->|Нет| D[Чтение с диска] D --> E[Загрузка в кэш] E --> C

Пограничные кейсы

🚫

Переполнение типа — критическая ошибка, которая может привести к потере данных или падению приложения.

Проблема переполнения

sql
-- Счётчик в TINYINT UNSIGNED (max 255)
UPDATE counters SET value = value + 1 WHERE id = 1;
 
-- Когда value = 255, следующий инкремент вызовет ошибку
-- или (в зависимости от настроек) обернётся в 0

Когда использовать BIGINT

sql
-- AUTO_INCREMENT ID для высоконагруженных систем
-- Twitter: миллиарды твитов
-- YouTube: миллиарды видео
 
CREATE TABLE tweets (
    id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    content TEXT,
    created_at TIMESTAMP
);

INT UNSIGNED позволяет хранить ~4.3 миллиарда записей. Для большинства проектов этого достаточно на годы работы.


Рекомендации по выбору типа

СценарийРекомендуемый типОбоснование
Булевые значения (0/1)TINYINT(1)1 байт, явная семантика
Возраст, рейтинг (1-5)TINYINTДиапазона 0-255 достаточно
ГодSMALLINT0-65535 покрывает все года
Количество товаровSMALLINT/INTЗависит от масштаба бизнеса
ID записейINT UNSIGNED4.3 млрд записей — достаточно для 99% проектов
Большие счётчикиBIGINTПросмотры, лайки в соцсетях

Плюсы и минусы разных подходов

ПодходПлюсыМинусы
Всегда BIGINTНикогда не переполнитсяРасход места и памяти × 8
Точный подбор типаОптимальное использование ресурсовТребует анализа данных
TINYINT для всегоМинимальный размерРиск переполнения

Вопросы интервьюера

Q: Почему бы не использовать BIGINT везде для надёжности?

Это приводит к 8-кратному увеличению размера данных по сравнению с TINYINT. На больших таблицах это терабайты лишнего места, замедление запросов и увеличение стоимости хранения.

Q: Как понять, какой тип выбрать?

Оцените максимальное значение, которое может быть в колонке. Добавьте запас на рост. Выберите минимальный тип, который покрывает этот диапазон.

Q: Что произойдёт при переполнении типа?

Зависит от настроек SQL_MODE. Может быть ошибка, обрезание значения до максимума, или "заворачивание" (wrap around) к минимальному значению.

Q: Влияет ли тип колонки на размер NULL?

NULL хранится отдельно (обычно 1 бит на колонку в битовой маске), размер типа на NULL не влияет.


Источники