Тінінт проти Біта?


81

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

Єдині відмінності, про які я знаю:

  • bit: розмір зберігання - 1 біт, можливі значення - 0 або 1
  • tinyint: розмір сховища - 1 байт, можливі значення - 0-255

Який тип даних кращий, коли вам потрібно представити логічні значення? Чи tinyintварто додаткові накладні витрати "про всяк випадок", коли вам потрібно значення> 1?


1
“Про всяк випадок” здається досить плавним дизайном бази даних. Чому б не зберегти все як NVARCHAR (MAX) і не покрити всі свої бази?
Стюарт Ейнсворт

TinyInt - це моя перевага. Тоді, виконуючи агрегований підрахунок поля, вам не потрібно його кидати. Крім того, деякі інтерфейсні мови інтерпретують біт інакше, ніж інші, і використання TinyInt робить перевірки перевірки універсальними для будь-якої інтерфейсної мови.
Грегорі Харт

Я щойно зіткнувся з дивністю з bit в phpMyAdmin. Коли я кажу йому, щоб поле було NULL і не встановлено значення за замовчуванням, воно за замовчуванням має значення <em> NULL </em> замість NULL. +1 для tinyint btw
Vörös

при імпорті форми файл csv 1 працює у випадку tinyint (1), але у випадку біта (1) вам доведеться замінити його на b'1 '
Раджат,

Відповіді:


90

Коли ви додаєте бітовий стовпець до вашої таблиці, він буде займати цілий байт у кожному записі, а не лише один біт. Коли ви додасте другий бітовий стовпець, він буде зберігатися в тому ж байті. Для стовпця дев’ятого біта буде потрібно другий байт пам’яті. Таблиці з 1-бітовим стовпцем не отримають жодної переваги для зберігання.

І Tinyint, і біт можна змусити працювати, і я успішно використовував їх, і не маю сильних переваг.


Це дуже корисний коментар, і ваша репутація досить гарна, але чи є у вас посилання на його підтримку? Це деталь реалізації чи всі двигуни обробляють це однаково?
Jon z

3
@Jonz Дивіться тут MySQL.
shmosel

З посилання на @shmosel цілком зрозуміло, що 1 бітний (1) стовпець займає 1 байт, але не настільки зрозуміло, що два, три, чотири ... поки вісім бітових (1) стовпців не приймають однаковий байт. Я шукав це в Інтернеті без успіху. Чи не могли б ви посилатись і на це? Мені цікаво просто знати, чи, якщо у мене є, скажімо, чотири логічні стовпці, які мені потрібні для моєї таблиці, може бути варто використовувати стовпець bit (1) замість tinyint (1), щоб заощадити місце для зберігання. Дякую.
assensi

@assensi Гарна думка. Ви завжди можете використовувати один BIT(n)замість nполів. Або ви можете використовувати звичайний INTі зберігати кожен логічний вигляд як біт. Але якщо ви збираєтеся з окремими полями, я думаю , TINYINTяк правило , кращим , щоб BITв MySQL.
shmosel

19

Біт ... якщо ви не з клану "true / false / file not found"

Якщо ви не отримали посилання ...

А у випадку з Linq2SQL, біт працює з true / false, що полегшує програмування. У обох є переваги.

І тут також слід розглянути програмування. Що станеться, якщо ви (або молодший програміст-інтерн) використовуєте 2, 3, 25, 41, 167, 200 тощо? Де це задокументовано? Біти є самодокументуючими і досить універсальними.


11
біти обнуляються, тому ви все ще можете мати T / F / FNF.
Остін Салонен

3
І наскільки зло NULL дорівнює FNF? :) Воістину гідний thedailywtf!
Джон Руді

@Pratik проблема NULL означає, що в базі даних немає значення. Це не означає, що файл не знайдено. Зробіть це, і ви почнете неявно кодувати стани у свої рядки, які важко задокументувати та заплутати. Начебто, як таблиця предметів. Як я можу зрозуміти, чи товар був проданий? Я міг би подивитися, чи є у нього ціна продажу, дата продажу, ім’я покупця і т. Д. Або я міг застосувати все це за допомогою обмеження перевірки та створити бітове поле для проданих товарів.
CodeMonkey

15

Я використовую біти, коли це доречно. Окрім того, що це семантично правильний тип (кількість семантики!), Кілька бітових полів (до 8) в одному рядку (у будь-якому випадку на SQL Server) можуть бути об'єднані в один байт сховища. Після восьмого потрібен додатковий байт для наступних 8 тощо.

Список літератури:


5

12
Хммм, це більше схоже на запис "Чому б вам не використовувати MySQL" ... :-)
Брайан Ноблауч

1
виправлено: зазначається у 5.0.23, 5.1.12 журналах змін. Стовпці BIT у таблиці можуть призвести до збою об’єднань, які використовують таблицю.
Antti Rytsölä


2

Булеве значення, за визначенням, допускає лише два значення. Навіщо для цього вам потрібно щось більше, ніж один біт? якщо вам потрібна логіка з трьома (або більше) станами, тоді використовуйте більший тип даних, але я б (і справді) дотримувався бітових полів для стандартної логічної логіки.


2

Я використовую біт, тому що це економить мені необхідність використовувати обмеження перевірки, а також тому, що моя ORM автоматично перетворює біт у логічний тип (C #), який може бути обнулений, що я дуже ціную, коли кодую.


2

Нульовий простір для помилкового

Незалежно від вашого вибору, ви можете встановити NULLзамість цього, 0і це не займе зайвого місця (оскільки база даних майже завжди має NULLпрапор для кожного поля кожного рядка, просто сидячи там; більше інформації тут ). Якщо ви також переконаєтесь, що значення за замовчуванням / найімовірніше false, ви заощадите ще більше місця!

Дещо простору для правди

Значення для представлення trueвимагає простору, визначеного типом поля; Використання BITдозволить заощадити місце, лише якщо таблиця має кілька таких стовпців, оскільки вона використовує один байт на 8 полів (на відміну від того, TINYINTякий використовує один байт на поле).

TINYINTмає ту перевагу, що дозволяє налаштувати 8- значну бітову маску не турбуючись про керування купу додаткових стовпців, а пошук теоретично швидший (одне ціле поле проти кількох бітових полів). Але є деякі недоліки, такі як повільніше впорядкування, вишукані матеріали для перехресного індексування та відсутність назв полів. Що для мене найбільша втрата; вашій базі даних знадобиться зовнішня документація, щоб зазначити, які біти що робили в яких бітових масках.

У будь-якому випадку уникайте спокуси використовувати TEXTполя для зберігання логічних чи наборів з них. Пошук тексту - це набагато більше роботи для сервера, і довільні схеми імен, такі як "увімкнути, вимкнути, вимкнути", можуть зашкодити сумісності.


1

Я просто спробував згрупувати за бітом (SQL Server 2k5), і він у мене спрацював добре. Мені подобається використовувати правильний тип даних для програми. Якщо це поле true / false, тоді я використовую біт ...


1

Всі ці теоретичні дискусії чудові, але насправді, принаймні, якщо ви використовуєте MySQL і справді для SQLServer, найкраще дотримуватися недвійкових даних для своїх логічних даних з тієї простої причини, що з ними легше працювати виводить дані, запитує тощо. Це особливо важливо, якщо ви намагаєтесь досягти взаємодії між MySQL та SQLServer (тобто ви синхронізуєте дані між ними), оскільки обробка типу даних BIT у них двох відрізняється. ТАК на практиці у вас буде набагато менше клопоту, якщо ви будете дотримуватися числового типу даних. Я рекомендую MySQL дотримуватися BOOL або BOOLEAN, які зберігаються як TINYINT (1). Навіть те, як MySQL Workbench та MySQL Administrator відображають тип даних BIT, не є приємним (це маленький символ для двійкових даних).


1

Не думаю, що я бачив це згадане вище, але існує проблема неможливості агрегувати стовпці BIT (наприклад, MIN, MAX та особливо SUM). Я щойно перевірив використання 2008 року, і проблема все ще є. Це найбільша причина, чому я останнім часом використовую tinyint - інше, що мені подобається, як масштабується tinyint - це завжди болісно, ​​коли твій бітовий прапор «двозначного» раптом потребує більше можливих значень.


1
Ви можете агрегувати їх, перекинувши їх на інший тип даних - Навіщо ж вам потрібно підсумовувати true / false?
Martin Smith

2
Ми часто групуємося в одному полі та підсумовуємо, скільки іншого поля відповідає дійсності для кожної групи за результатом, альтернативою sum може бути повернення цілого результату до коду та його циклічне проведення, іноді в результаті повернення клієнту 1000 разів більше даних . Але кастинг усуває це, тож це не проблема.
Девід Мортенсон

0

Ми будуємо всі наші таблиці з полем int "vector". Потім ми використовуємо це поле як колекцію з 32 бітів, яку ми можемо призначити для будь-якої мети. (Потенційно використання групи бітів для набору станів). Уникає необхідності продовжувати додавати в поля прапорів, якщо ми забули.


2
Це також називається затемненням. Або, для неспеціаліста, "кошмар обслуговування".
Роберт К. Барт,

6
Ви можете просто зробити всі свої таблиці єдиним стовпцем TEXT і помістити все туди, розділені комами. Тоді вам ніколи не доведеться змінювати модель даних.
Tom H

1
У нас є дещо унікальне середовище. Ми маємо надзвичайно великі набори даних І час безвідмовної роботи 4 9, тому зміна таблиць є досить забороняючою (вдвічі більшою, ніж у випадках реплікації). Ми відстежуємо всі біти в централізованому місці, що допомагає уникнути проблем з технічним обслуговуванням.
Джо

0

@Kevin: Я вважаю, що ти можеш використовувати group byбітові поля (SQL Server 2005):

declare @t table (
    descr varchar(10),
    myBit1 bit, 
    myBit2 bit
)
insert into @t values ('test1', 0, 1)
insert into @t values ('test2', 1, 0)
insert into @t values ('test3', 1, 1)
insert into @t values ('test4', 0, 0)

select myBit1, count(myBit1) from @t group by myBit1
select myBit2, count(myBit1) from @t group by myBit2

Результати:

myBit1 
------ -----------
0      2
1      2

myBit2 
------ -----------
0      2
1      2

0

TinyInt - це моя перевага. Тоді, виконуючи агрегований підрахунок поля, вам не потрібно його кидати. Крім того, деякі інтерфейсні мови інтерпретують біт інакше, ніж інші, і використання TinyInt робить перевірки перевірки універсальними для будь-якої інтерфейсної мови.



-2

Мені подобається використовувати char (1) із 'T' або 'F'. Так, ним можна зловживати з іншими значеннями, але принаймні його легко переглядати у звітах або інших місцях, де з бітовими або двійковими значеннями важче працювати.


2
Ви можете (і повинні) легко додати обмеження до стовпця, щоб дозволити лише "T" і "F". З огляду на це, рівень звітності повинен бути ЦІЛЬКО ВІДДЕЛЕНИМ від бази даних. Не слід змінювати схему бази даних лише для того, як відображатиметься стовпець.
Tom H

Я згоден з Деррілом. Враховуючи відсутність підтримки логічних типів у загальних системах СУБД (MySQL тут не самотня) T / F (насправді я віддаю перевагу Y / N) набагато читабельніший. Хоча я принципово погоджуюся з коментарями Тома Х., я думаю, що читабельність набагато важливіша, ніж він надає кредит. Розробники баз даних не дивляться на інтерфейс, змінюючи чужий код! Крім того, не завжди зрозуміло, яким чином розробник вважає 1 і 0. Якби ми всі робили це «належним» старомодним способом, ми б використовували -1для представлення істини та 0для представлення помилки.
cartbeforehorse

До мого попереднього коментаря я повинен додати, що, схоже, MySQL не підтримує обмеження CHECK, що ускладнить опцію T / F, оскільки ви не можете запобігти заповненню стовпця будь-яким іншим символом алфавіту. Не гарно.
cartbeforehorse
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.