Коли використовувати TINYINT над INT?


91

Взагалі, я завжди використовую Інти. Я знаю, що теоретично це не найкраща практика, оскільки ви повинні використовувати найменший тип даних, який гарантовано зберігатиме дані.

Наприклад, краще використовувати, tinyintколи ви знаєте, що єдині дані, які ви будете зберігати, - це 1, 0 або нуль (з дуже малим шансом розширити їх на 2 або 3 пізніше).

Однак єдина причина, яку я знаю для цього - це для зберігання даних - використання 1 байта в рядку замість 4 байтів.

Які наслідки використання tinyint(або smallintнавіть навіть bigint) просто int, крім економії місця на жорсткому диску?


2
Це дуже приємний питання (+1). MySQL має SELECT ... ANALYZE PROCEDURE (), який фактично рекомендує найменші типи даних, які таблиця повинна мати для даного SELECT. Це почасти було натхненником моєї відповіді.
RolandoMySQLDBA

3
Хороше запитання, але для точного діапазону крихітних точок є 0-255. Бітове поле дорівнює 0 або 1 (або NULL). Вартість зберігання мініатюри - 1 байт. Кожні 8-бітові поля в таблиці коштуватимуть 1 байта пам’яті. msdn.microsoft.com/en-us/library/ms187745.aspx та msdn.microsoft.com/en-us/library/ms177603.aspx
billinkc

@billinkc Праворуч. Ось чому я згадав про можливість розширення стовпця на значення 2 або 3. Якщо ви включите 2 або 3, вам доведеться використовувати tinyint (у найменшій шкалі).
Річард

1
"Наприклад, краще використовувати tinyint, коли ви знаєте, що єдині дані, які ви будете зберігати, - це 1, 0 або null (з дуже малим шансом розширити їх на 2 або 3 пізніше)." Я б використав ENUM для такого. Вони зберігаються як бітові поля, і, як багато інших вказували тут, невеликі заощадження на запис складають великі заощадження на всій базі даних - ще більше, якщо стовпчик індексується.

2
@ user6665 I'd use an ENUM for such a thing.Не на SQL Server, ви не хочете, оскільки не має жодного перерахунку.
підкреслюйте_d

Відповіді:


92

Місце на диску дешево ... в цьому справа не в цьому!

Перестаньте думати щодо місця для пам’яті, замість цього подумайте про пул буфера та пропускну здатність пам’яті . Зрештою, пропускна здатність кешу процесора та шини пам'яті . Пов'язана стаття є частиною серії, що висвітлює проблеми з поганим вибором кластеризованих ключів (INT проти GUID проти послідовного GUID), але в ній висвітлено різницю байтів.

Переважне повідомлення - це питання дизайну. Різниця не відображатиметься в окремій базі даних на відповідному специфічному сервері, поки ви не потрапите на територію VLDB, але якщо ви можете зберегти кілька байт, чому б не зробити це.

Мені нагадали про оточення, описане в попередньому запитанні . 400+ баз даних, розміром від 50 Мб до 50 ГБ, на екземпляр SQL. Вичищення декількох байт на запис, на таблицю, на базу даних у цьому середовищі може суттєво змінитись.


29

Окрім інших відповідей ...

Рядки та записи індексів зберігаються на 8-ти сторінках. Таким чином, мільйон рядків по 3 байти в рядку не має 3 МБ на диску: це впливає на кількість рядків на сторінці ("щільність сторінки").

Це ж стосується і nvarchar до varchar, smalldatetime to datetime, int to tinyint тощо

Редагувати, червень 2013 року

http://sqlblog.com/blogs/joe_chang/archive/2013/06/16/load-test-manifesto.aspx

У цій статті зазначено

Важливими критеріями є кардинальність та співвідношення сторінки до рядків.

Отже, вибір типу даних має значення


5
Влучне зауваження. Абсолютний найгірший приклад - це рядок 4028 байтів, що складається з стовпців повністю фіксованої довжини, до яких потрібно додати стовпець. Додавання маленькогоintint переведе вас до 4030 (2 рядки на сторінку), але інт пересуне вас через межу (1 рядок на сторінку, 4028 байтів витрачено на сторінку).
Марк Сторі-Сміт

Я колись робив тест на ефективність проти int vs bigint. Збереження 1 мільйона записів, порівняння часу та місця зберігання та отримання їх по черзі, знову вимірюючи ефективність. Я не бачив великих відмінностей. Я збираюся зробити такий же тест на ефективність для int vs tinyint. Я дійсно думаю, що цим можна нехтувати 80% застосувань, що призводить до більш послідовних типів даних та менших витрат на обслуговування.
Саїд Неаматі

1
@SaeedNeamati Ви можете прочитати статтю з відповіді Марка (" Ви коли-небудь чули ... давайте просто це зробимо - пізніше будемо хвилюватися про продуктивність? ... Я це чую весь час ... ") і gbn тут . Я думаю, що додому можна сказати, що будь-який неефективний вибір демонструє свої смуги в потрібному масштабі, а кишка ОП не помиляється.
ruffin

14

Це не тільки зберігання таблиць. Якщо ви використовуєте індекси, де стовпець int є частиною складеного ключа, ви, звичайно, хочете, щоб сторінки індексів були максимально повними, це було результатом записів якомога менше.

Я, безумовно, сподіваюся виявити, що вивчення записів індексу на сторінках BTREE буде трохи швидше при менших типах даних. Однак будь-які VARCHAR, що беруть участь у записах індексів, компенсують (анулюють) приріст продуктивності від використання TINYINT над INT.

Незважаючи на те, що якщо записи в індексі мають складені записи, і всі цілі числа, то менші цілі числа є побіжно, тим краще і швидше.


13

Усі речі набувають складності, коли бази даних збільшуються:

  • вікна технічного обслуговування потрібно збільшити або перенести
  • резервні копії (повна резервна копія в кінці дня стає абсурдною їжею часу, тому вам потрібні диференційні або навіть резервні копії та виконувати повний раз на тиждень, можливо, раз на місяць)
  • Виконання вистав стає перебігом часу (створення індексу в багатомільйонній таблиці займає не тривіальний час для виконання) і його потрібно перенести і погіршити, якщо таблиця широка ...
  • І передавання того, що резервне копіювання 100Gb через мережу - це не те, що я називаю шматок пирога - особливо якщо мережа (з незрозумілої причини) вперта на перерву підключення на позначці 75Gb ... (сталося з установкою, над якою я працював, робив резервну копію на картографічному диску в мережі - мережі) ...

І які типи даних пов’язані з цим? ВСЕ. Використання розмірів рядків, більших за необхідне, призводить до заповнення сторінок бази даних раніше, ніж потрібно, або навіть витрачання місця, якщо розмір рядка такий, що на сторінці не може бути записано не більше одного запису. Результат - більше сторінок, необхідних для написання та читання, більше пам’яті оперативної пам’яті використовується для кешування, що (для великих записів потрібна більша пам’ять). А оскільки ваші типи даних вказані більше, ніж потрібно на диску, ваші індекси зазнають тієї ж проблеми - особливо, якщо ви кластеризуєте цей первинний ключ з 2 BIGINT стовпців, оскільки будь-які інші створені індекси копіюють цей первинний ключ неявно під їх визначення.

Якщо ви знаєте, що в деяких стовпцях таблиці, що міститимуть мільйони рядків або навіть маленьку таблицю, буде FK'ed багатомільйонний ряд, якому не потрібно 4-байтне ціле число для зберігання своїх даних, але 2-байт буде достатньо - використовуйте SMALLINT . Якщо значень в діапазоні 0-255 достатньо, TINYINT . Прапор так / ні? Є БІТ .


9

Хоча для tinyintvs intіснують чіткі відмінності, такі як дисковий простір, розбиття сторінок та час обслуговування, для них не було б нічого varchar.

То чому б не оголосити всі текстові поля як varchar(4000), оскільки це все одно буде використовувати лише необхідний простір? Ще більше вам буде гарантовано, що ваші дані ніколи не будуть врізані.

Відповідь звичайно:

  1. Уточнення своїх намірів (оскільки ніхто не зрозуміє, чому в полі імені має бути 4000 символів)
  2. Перевірка, як ви хочете, щоб ніхто не вводив всю біографію як ім'я.

Ці самі причини стосуються tinyintі цього.


3
Це старша тема, але уточнення та перевірка - не єдина причина. Якщо у вас є VARCHAR (4000) для чогось, що має бути VARCHAR (20), план запитів подумає, що ваші вимоги до пам'яті та процесора є багато кратними, ніж вони мають бути щодо цього стовпця. Я не витрачав часу на це, але я здогадуюсь, що ви, мабуть, це побачите, переглянувши план запитів для VARCHAR (20), а потім перейдіть до VARCHAR (4000) і перевірте передбачувані витрати.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.