Що отримують реляційні бази даних, встановлюючи заздалегідь визначений тип даних для кожного стовпця?


44

Я зараз працюю з базою даних SQL, і це завжди викликало цікавість, але пошук Google не сильно розгортається: чому строгі типи даних?

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

Але те, що я не розумію, полягає в тому, яка вигода від того, що існує стільки різних типів даних:

  • Чому mediumtext, longtextі text?
  • Чому decimal, floatі int?
  • тощо.

Яка користь сказати базі даних "У записах до цього стовпця буде лише 256 байт даних простого тексту." або "Цей стовпець може містити текстові записи до 16 777 215 байт"?

Це користь від ефективності? Якщо так, то чому знати розмір запису перед рукою допомагає виконанню? А точніше, це взагалі щось інше?


2
Я подумав, що це питання вже повинно існувати тут, але я шукав сайт і не знайшов нічого корисного.
John Doe

1

6
Якби у вас не було різних decimal, floatта intтипів, що б ви очікували 1 / 3зробити? Про що 1.0 / 3.0? Чи можете ви бути впевнені, що, поділившись columnAна columnBце, ви отримаєте очікувані результати?
Ендрю каже, що повернеться до Моніки

2
@johndoe Я не думаю, що це колись буде необхідним, але це може бути дуже зручно. Скажімо, ви хочете застосувати обмеження, що товарний запас магазину не може бути нижчим за 5% від їх очікуваних щомісячних продажів. Або ви хочете, щоб загальний бюджет кожного підрозділу становив не більше 20% від загального бюджету. Він також може з'являтися в обчислюваних стовпцях, які потрібно обчислити однаково у кількох додатках, використовуючи одну і ту ж базу даних.
Ендрю каже, що знову

2
Варто зазначити, що SQLite не встановлює заздалегідь визначений тип на стовпчик : "SQLite" не має типу ". Це означає, що ви можете зберігати будь-які потрібні вам дані в будь-якому стовпчику будь-якої таблиці, незалежно від заявленого типу даних цього стовпця. "
Прем'єр

Відповіді:


50

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

По своїй суті SQL призначений для визначення даних ( DDL ) та доступу до даних ( DML ) в системі реляційних баз даних . Статичне введення тексту дає ряд переваг порівняно з динамічним набором тексту для цього типу системи.

  • Покажчики , які використовуються для швидкого доступу до певних записів, дуже добре працюють, коли розмір фіксований. Розглянемо запит, який використовує індекс, можливо, з декількома полями: якщо типи даних і розміри відомі достроково, я можу дуже швидко порівняти свій предикат (WHERE пункт або приєднатися до критеріїв) зі значеннями в індексі та швидше знайти потрібні записи .

  • Розглянемо два цілих значення. У системі динамічного типу вони можуть бути змінного розміру (думаю, що Java BigInteger, або вбудовані цілі числа довільної точності Python). Якщо я хочу порівняти цілі числа, я спершу повинен знати їх бітну довжину. Це аспект цілого порівняння, який значною мірою прихований сучасними мовами, але є дуже реальним на рівні процесора. Якщо розміри зафіксовані і відомі достроково, з процесу видаляється цілий крок. Знову ж таки, бази даних повинні мати можливість обробляти мільйони транзакцій якнайшвидше. Швидкість - король.

  • SQL був розроблений ще в 1970-х. У попередні дні мікрокомп'ютерів пам’ять була розціненою. Обмеження даних допомогло контролювати вимоги зберігання. Якщо ціле число ніколи не переростає один байт, навіщо виділяти йому більше пам’яті? Це марний простір в епоху обмеженої пам’яті. Навіть у сучасний час ці зайві витрачені байти можуть додавати та знищувати продуктивність кешу CPU. Пам'ятайте, що це двигуни бази даних, які можуть обслуговувати сотні транзакцій в секунду, а не лише ваше маленьке середовище розробки.

  • По лінії обмеженого сховища корисно мати змогу помістити в пам'ять один запис на одній сторінці. Після переходу на одну сторінку з’являються більше пропусків сторінки та більш повільний доступ до пам'яті. Нові двигуни мають оптимізацію, щоб зменшити проблему, але вона все ще існує. Правильно розміряючи дані, ви можете зменшити цей ризик.

  • Крім того, в сучасний час SQL використовується для підключення до інших мов через ORM або ODBC або якийсь інший шар. У деяких із цих мов є правила про необхідність отримання міцних, статичних типів. Найкраще відповідати більш суворим вимогам, оскільки динамічно набрані мови можуть працювати зі статичними типами простіше, ніж навпаки.

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

Цікаво відзначити, що існують реалізації SQL, які не сильно набрані. SQLite - це, мабуть, найпопулярніший приклад такого механізму реляційних баз даних. Знову ж таки, він розроблений для однопотокового використання в одній системі, тому проблеми щодо продуктивності можуть бути не такими яскраво вираженими, як, наприклад, база даних Oracle, що обслуговує мільйони запитів в хвилину.


У SQLite є типи даних, які розрізняють числові та текстові дані, але лише 5 "класів" зберігання даних: sqlite.org/datatype3.html
FrustratedWithFormsDesigner

1
@FrustratedWithFormsDesigner Я знаю, але він все ще ніде не є настільки суворим, як такі двигуни, як SQL Server, Oracle або PostgreSQL.

SQL має не лише статичний тип - завдяки наявності обмежень перевірки, він ефективно підтримує типи уточнення.
садок

4
Хоча мається на увазі в першій пулі Indexes, в основному зазначено: Наявність типу даних дозволяє двигуну бази даних зрозуміти дані , порівняння (більші / менші числа, більш ранні / пізні дати-дати, до / після в алфавіті), і тому дозволяє сортувати та запитувати .
Василь Бурк

Тож якщо розміри важливі ... і sql потрібно знати заздалегідь ... який саме розмір транзакцій на "Zillion"?
WernerCD

24

По-перше: звичайний текст є двійковим (це навіть не символи UTF8 або ASCII "0" і "1", а фактичні біти включення / вимкнення)

Однак, деякі причини:

  • Обмеження для бізнесу / дизайну: дозволяти число 7626355112 у стовпці HEIGHT таблиці "ОСОБА" було б неправильним. Дозволити "Howya" у стовпці "ДАТА" Рахунку-фактури було б неправильним.
  • Менш схильний до помилок код: вам не потрібно писати код, щоб переконатися, що дані, отримані з стовпця дати, справді є датою. Якщо типи стовпців були динамічними, вам доведеться зробити багато перевірок типів під час читання.
  • Ефективність обчислень: Якщо стовпець типу INTEGER, а ви SUM () це, RDBMS не повинен застосовувати арифметику з плаваючою комою.
  • Ефективність зберігання: заявляючи, що стовпчик VARCHAR (10), дозволяє RDBMS виділяти простір більш точно.
  • Посилальна цілісність та єдиність: PK (або FK) таблиці не повинні допускати поплавків, оскільки рівність з плаваючою комою є хитрою, тому ви повинні оголосити їх у неплаваючому типі, як символи чи цілі числа.
  • Існують RDBMS з динамічними (не суворими) типами стовпців (SQLite) . Він використовує концепцію "тип спорідненості", але все ще дозволяє вставити практично будь-що у будь-який стовпець, не нарікаючи. Є компроміси, про які тут не піде мова. Дивіться це питання .

8

Це так, що базовий код, в який записана база даних, може виділяти та використовувати записи фіксованого розміру, якщо він знає, що певне поле може містити від 0 до 256 символів тексту, то він може виділити блок з 256 байтів, щоб зберігати його.

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


Якби тільки всі відповіді могли бути цією стислою і
Даррен Рінгер

6

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

1) коли двигун бази даних переходить рядки в таблиці, він не повинен робити фантазійного аналізу, щоб визначити, де закінчується кожен запис, він може просто знати, що кожен рядок складається з, скажімо, 32 байт, і так, щоб отримати наступного запису достатньо додати 32 байти до поточного місця записів.

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


Поля фіксованої довжини можуть зробити обробку більш ефективною через послідовну довжину запису та зміщення полів, але поля змінної довжини можуть звести нанівець ці переваги, оскільки довжина запису та зміщення полів можуть змінюватися. Так само стиснення рівня запису призведе до записів змінної довжини, тому розташування заданого запису не може бути просто обчислено.
Zenilogix

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

3

Ви запитали, чому СУБД мають статичні типи даних.

  1. Швидкість пошуку. Вся суть СУБД полягає в тому, щоб зберігати набагато більше даних, ніж ви могли б завантажувати в програму. Подумайте, "усі фішки кредитної картки, створені у світі за останні десять років". Для ефективного пошуку таких даних корисні типи даних фіксованої довжини. Особливо це стосується структурованих даних, таких як штампи дати та номери рахунків. Якщо ви знаєте, з чим ви маєте справу достроково, простіше завантажувати ефективні індекси.

  2. Цілісність і обмеження. Простіше зберігати дані чистими, якщо у них є фіксовані типи даних.

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

  4. Прокляття клієнтської бази. На сьогодні RDBMS - це дуже складні, високооптимізовані програмні пакети, і вони вже десятиліттями використовують накопичення даних. Вони зрілі. Вони працюють. Збій RDBMS, що призводить до великої втрати даних, в цей час надзвичайно рідкісний. Перехід на щось із більш гнучкою системою набору даних не є вартістю або ризиком для більшості організацій.

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


3

Загалом, чим більше докладно ви повідомляєте базу даних про те, що ви зберігаєте, тим більше можна спробувати оптимізувати різні показники продуктивності, пов’язані з цими даними, наприклад, скільки місця на диск викласти або скільки пам'яті виділити під час його отримання. .

Чому середній текст, довгий текст і текст?

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

Чому десятковий, плаваючий і int?

Різні рівні точності вимагають різного обсягу зберігання, і не кожне використання вимагає найвищого ступеня точності. Наприклад, дивіться тут: https://docs.oracle.com/cd/B28359_01/server.111/b28286/sql_elements001.htm#SQLRF50950

Oracle має досить багато різних числових типів з різними вимогами до зберігання та різними можливостями з точки зору рівня точності та розміру числа, які можна представити.


2

Певною мірою це історично.

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

Додайте до цього файлу кілька індексів, і ви маєте початки реляційної бази даних.

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

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


1

Якщо база даних використовує записи фіксованого розміру, будь-який запис у базі даних буде продовжувати вміщуватися в тому самому місці, навіть якщо зміст її змісту. На противагу цьому, якщо база даних намагається зберігати записи, використовуючи саме обсяг пам’яті, необхідний для їхніх полів, зміна імені Емми Сміт на Емму Джонсон може призвести до того, що її запис буде занадто великим, щоб вмістити його в теперішньому місці. Якщо запис буде переміщено кудись з достатньою кількістю місця, будь-який індекс, який відстежує, де він знаходиться, потрібно буде оновити, щоб відобразити нове місце.

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


1

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

Яка користь сказати базі даних "У записах до цього стовпця буде лише 256 байт даних простого тексту." або "Цей стовпець може містити текстові записи до 16 777 215 байт"?

Як ви підозрюєте, причина полягає у ефективності. Абстракції просочуються . Запит подібний SELECT author FROM booksможе запускатися досить швидко, коли розмір усіх полів у таблиці відомий.

Як каже Джоел,

Як реалізується реляційна база даних SELECT author FROM books? У реляційній базі даних кожен рядок таблиці (наприклад, таблиця книг) має однакову довжину в байтах, і кожне поле завжди знаходиться з фіксованим зміщенням від початку рядка. Так, наприклад, якщо кожен запис у таблиці книг має довжину 100 байт, а поле автора - зі зміщенням 23, то автори зберігаються в байтах 23, 123, 223, 323 і т. Д. До якого коду потрібно перемістити наступний запис у результаті цього запиту? В основному, це так:

pointer += 100;

Одна інструкція процесора. Фаааааааааст.

Багато часу ви працюєте досить далеко від нітроподібної основи, що про це вам не потрібно дбати. У PHP на основі веб - розробник, ви піклуєтеся про те , як багато інструкцій процесора в коді використовується? Більшість часу, ні, не дуже. Але іноді корисно знати з двох причин: це може пояснити рішення, прийняті вашими бібліотеками; а іноді вам потрібно дбати про швидкість у власному коді.

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