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


44

Я сейчас работаю с базой данных SQL, и это всегда вызывало у меня любопытство, но поиски в Google мало что показывают: почему строгие типы данных?

Я понимаю, почему у вас есть несколько разных типов данных, например, например, насколько важно различать двоичные и простые текстовые данные . Вместо того, чтобы хранить 1 и 0 двоичных данных в виде открытого текста, я теперь понимаю, что более эффективно хранить двоичные данные в своем собственном формате.

Но я не понимаю, какая польза от такого большого количества разных типов данных:

  • Почему mediumtext, longtextи text?
  • Почему decimal, floatи int?
  • и т.п.

В чем преимущество сообщения базы данных: «В этом столбце будет только 256 байтов данных в виде простого текста». или "Этот столбец может содержать текстовые записи длиной до 16 777 215 байт"?

Это выигрыш в производительности? Если так, то почему знание размера записи перед рукой помогает в производительности? Или скорее это что-то совсем другое?


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

1
Очень актуально: joelonsoftware.com/2001/12/11/back-to-basics
8bittree

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 или критерии JOIN) со значениями в индексе и быстрее найти нужные записи ,

  • Рассмотрим два целочисленных значения. В динамической системе типов они могут иметь переменный размер (например, Java BigIntegerили встроенные в Python целые числа произвольной точности). Если я хочу сравнить целые числа, мне нужно сначала узнать их длину в битах. Это аспект целочисленного сравнения, который в значительной степени скрыт современными языками, но очень реален на уровне процессора. Если размеры фиксированы и известны заранее, весь процесс удаляется из процесса. Опять же, предполагается, что базы данных смогут обрабатывать миллиарды транзакций как можно быстрее. Скорость - это король.

  • SQL был разработан еще в 1970-х годах. В первые дни микрокомпьютинга память была на высоте. Ограничение данных помогло контролировать требования к хранилищу. Если целое число никогда не превышает одного байта, зачем выделять для него больше памяти? Это пустое пространство в эпоху ограниченной памяти. Даже в наше время эти лишние потраченные байты могут увеличивать и снижать производительность кэша ЦП. Помните, что это движки баз данных, которые могут обслуживать сотни транзакций в секунду, а не только вашу маленькую среду разработки.

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

  • Moreso в наше время, 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 таблицы PERSON был бы неправильным. Разрешение «Howya» в столбце DATE СЧЕТА будет неверным.
  • Менее подверженный ошибкам код: вам не нужно писать код, чтобы убедиться, что данные, извлеченные из столбца даты, действительно являются датой. Если бы типы столбцов были динамическими, вам пришлось бы делать много проверок типов при их чтении.
  • Эффективность вычислений: если столбец имеет тип INTEGER, а вы SUM (), СУБД не нужно применять арифметику с плавающей запятой.
  • Эффективность хранения: указание на то, что столбец - VARCHAR (10), позволяет СУБД распределять пространство более точно.
  • Ссылочная целостность и уникальность: PK (или FK) таблицы не должны разрешать с плавающей точкой, так как равенство с плавающей запятой сложно, поэтому вы должны объявить их не в формате с плавающей запятой, как символы или целые числа.
  • Существуют РСУБД с динамическими (не строгими) типами столбцов (SQLite) . Он использует концепцию «сходства типов», в то же время позволяя вам вставлять практически все в любой столбец без жалоб. Есть компромиссы, которые здесь не обсуждаются. Смотрите этот вопрос .

8

Это происходит из-за того, что базовый код, в котором написана база данных, может выделять и использовать записи фиксированного размера, если он знает, что конкретное поле может содержать от 0 до 256 символов текста, то он может выделить блок из 256 байтов для его хранения.

Это значительно ускоряет процесс, например, вам не нужно выделять дополнительное хранилище по мере ввода пользователем данных, поскольку данное поле всегда начинает x байтов в записи, которую поиск или выбор в этом поле знает, чтобы всегда проверять x байтов в каждой записи и т. Д.


Если бы все ответы были такими краткими и
Даррен Рингер

6

Когда столбцы базы данных имеют определенные типы, типы обычно определяются сами по себе, чтобы иметь определенный размер в битах. В результате:

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

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


Поля фиксированной длины могут сделать обработку более эффективной из-за согласованной длины записи и смещений полей, но поля переменной длины могут аннулировать эти преимущества, поскольку длина записи и смещение полей могут различаться. Аналогично, сжатие на уровне записи приведет к записи переменной длины, поэтому местоположение данной записи просто не может быть вычислено.
Zenilogix

Это правда, и долгое время было общепринятым советом избегать полей переменной длины именно по этой причине. Я не знаю, как крупные игроки делают это, но кажется, что вы могли бы восстановить некоторые преимущества фиксированной длины, если бы механизм сохранял поля переменной ширины в невидимой для пользователя таблице или блоке памяти и имел бы первичные таблицы представления этих полей являются (фиксированной шириной) «указателем» на него. Учитывая, что вы должны регулярно выполнять полное сканирование полей переменной длины, во-первых, снижение производительности косвенного обращения может стоить поддерживать фиксированную ширину.
UserNotНайдено

3

Вы спросили, почему СУБД имеют статические типы данных.

  1. Скорость поиска. Смысл СУБД в том, чтобы хранить гораздо больше данных, чем вы могли бы загрузить в программу. Подумайте: «Все слипы кредитных карт, сгенерированные в мире за последние десять лет». Для эффективного поиска таких данных полезны типы данных фиксированной длины. Это особенно верно для структурированных данных, таких как отметки даты и номера счетов. Если вы заранее знаете, с чем имеете дело, проще загрузить эффективные индексы.

  2. Целостность и ограничения. Проще содержать данные в чистоте, если они имеют фиксированные типы данных.

  3. История. СУБД начали работать, когда у компьютеров было всего несколько мегабайт оперативной памяти, а объем хранения в терабайтах был чрезвычайно дорогим. Сохранение дюжины байтов в каждом ряду таблицы может сэкономить тысячи долларов и часов времени при таких обстоятельствах.

  4. Проклятие клиентской базы. СУБД сегодня являются очень сложными, высоко оптимизированными программными пакетами, и они используются для накопления данных в течение десятилетий. Они зрелые. Они работают. Сбой СУБД, приводящий к крупномасштабной потере данных, сегодня чрезвычайно редок. Переход на что-либо с более гибкой системой ввода данных не стоит затрат или риска для большинства организаций.

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


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;

Одна инструкция процессора. Faaaaaaaaaast.

Большую часть времени вы работаете достаточно далеко от мрачных оснований, которые вам не нужны. Как веб-разработчик на основе PHP, вы заботитесь о том, сколько инструкций процессора использует ваш код? В большинстве случаев нет, не совсем. Но иногда полезно знать по двум причинам: он может объяснить решения, принятые вашими библиотеками; и иногда вам нужно заботиться о скорости в вашем собственном коде.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.