Организация хранения данных в СУБД
Таблицы, имеющие первичный ключ, могут организовываться в кластер, т. е. все строки, соответствующие узлу B-дерева индекса, образуют единый блок, или кластер. Поскольку ключ первичный, подразумевается, что при поиске данных в таблице чаще всего будет использоваться именно он, т. е. будут использоваться условия типа WHERE ПолеПервичногоКлюча Больше-Меньше-Равно-и-т-д КакоеТоУсловие, поэтому поэтому при получении строк в таком запросе получаемые строки с большой вероятностью будут находится "рядом" друг с другом, в одном кластере, т. е. одним чтением из файла БД мы скорее всего прочитаем большое количество строк, соответствующих нашему условию. Получаем очевидное ускорение работы по сравнению с некластерно-организованной таблицей, где строки "разбросаны" и приходится делать много подгрузок из файла БД. К тому же кластер будет скорее всего представлять собой массив, а не связный список, поэтому доступ к элементам будет произвольный, что также ускоряет работу.
Как видим, таблица, имеющая первичный ключ, может быть кластерно-организованной.
Но в большинстве СУБД для всех (!) таблиц используется блочная (экстентная) организация таблиц.
СОБСТВЕННО ВОПРОС
Почему? Какие преимущества дает блочная (экстентная) организация?
Ведь если я кучу строк организую в единый блок, какую оптимизацию это даст, если это - просто сваленные в кучу строки, не имеющие, скорее всего, между собой ничего общего. Чем хуже, если я "раскидаю" строки по всему файлу БД?
Второй вопрос: зачем нужны табличные пространства? Опять же, я могу раскидать данные по всей БД.
P. S.
Вышеуказанный вопрос задается в связи с тем, что вся эта организация и внутренняя структура хорошо описана во многих книгах, но, к сожалению, вряд ли указаны причины именно такой организации. Я, често говоря, не очень искал, но не думаю, что это можно найти в какой-либо литературе. Просто хочу услышать ваши соображения.
Не припоминаю в Oracle понятие кластера. Это из MS SQL взято?
[QUOTE=cheburator]Но в большинстве СУБД для всех (!) таблиц используется блочная (экстентная) организация таблиц.[/QUOTE]
Блоки и экстенты - разные уровни, смешивать их нельзя.
[QUOTE=cheburator]Почему? Какие преимущества дает блочная (экстентная) организация?[/QUOTE]
Блочная - никаких преимуществ не дает, это следствие линейности используемых носителей. Экстентная - способ обойти линейность на более высоком уровне инкапсуляции.
[QUOTE=cheburator]Ведь если я кучу строк организую в единый блок, какую оптимизацию это даст, если это - просто сваленные в кучу строки, не имеющие, скорее всего, между собой ничего общего.[/QUOTE]
В Oracle чаще всего используются таблицы, организованные в куче и организованные по индексу. Второй тип подходит под твое "кластерное" описание.
В реляционной модели физическая последовательность записей в таблице не определена. Логическая же для таблиц по куче также не определена, а для организованных по индексу определяется первичным ключом.
[QUOTE=cheburator]Чем хуже, если я "раскидаю" строки по всему файлу БД?[/QUOTE]
Каким образом?
[QUOTE=cheburator]Второй вопрос: зачем нужны табличные пространства? Опять же, я могу раскидать данные по всей БД.[/QUOTE]
Уже отвечал. БД по определению никак не связана с аппаратными устройствами. Табличные пространства - способ установить связь на логическом уровне. Из всех СУБД, по-моему, они только в Oracle присутствуют.
[/quote]
неа. есть такое и в Oracle.
[QUOTE=Freeman]Блочная - никаких преимуществ не дает, это следствие линейности используемых носителей. Экстентная - способ обойти линейность на более высоком уровне инкапсуляции.[/QUOTE]
- о какой линейности идет речь и причем тут инкапсуляция?
[QUOTE=Freeman]Cheburator: Чем хуже, если я "раскидаю" строки по всему файлу БД?
Freeman: Каким образом?[/QUOTE]
Объясняю. Знаешь, что такое куча в оперативной памяти? Это когда при очередном запросе блока памяти выделяется первый попавшийся свободный блок подходящего размера. Так же и в этом случае: ищем первый попавшийся блок в файле БД и выделяем его для очередной строки. Таким образом, файл БД фрагментируется (точнее, каждая отдельно взятая таблица), ее строки "раскиданы" по всему файлу.
Блочная же организация, я так понимаю, работает так: место в файле выделяется большими блоками, рассчитанными на хранение большого количества строк. Как только блок заполняется, выделяется еще один и т. д. Но смысл?
Насчет твоей ссылки, где ты писал:
[QUOTE=Freeman]Файлы могут храниться на разных устройствах SCSI, например. При правильной организации хранения запросы на чтение, скажем, блоков индексов и блоков таблиц будут выполняться параллельно.[/QUOTE]
Как они выполняются параллельно, если для того, чтобы прочитать данные из таблицы, нужно их сначала найти по индексу? Т. е. сначала считывается индекс, находятся нужные строки, затем уж считываются строки из таблицы. Насколько я понимаю.
Я про Seek в потоке. Поток линеен. Для удобства его делят на блоки, но размер блока диктуется эффективностью работы аппаратных средств. Экстент же - логическая единица, выбираемая по прикладной потребности.
[QUOTE=cheburator]Блочная же организация, я так понимаю, работает так: место в файле выделяется большими блоками, рассчитанными на хранение большого количества строк. Как только блок заполняется, выделяется еще один и т. д. Но смысл?[/QUOTE]
Базы разные нужны, базы разные важны. Не приходилось видеть базу из нескольких сотен, или (боже упаси!) тысяч таблиц? Можешь прикинуть, какой там разброс будет? Часть таблиц - справочники, небольшого размера и практически неизменяемые. А нечто вроде "Главной книги проводок" - невъе..нного размера, плюс каждый день растет.
Много возможностей в СУБД реализовано "на вырост". С данными шутки плохи, и неизвестно, что завтра понадобится при решении задачи. Не будешь же каждый раз ядро переписывать. Тем более, что там сплошная математика - заплаты не прокатят.
Элементарно, чтобы при экспорте/импорте, когда размер таблиц уже известен, выделить сразу экстент нужного размера, соответствующая возможность должна быть предусмотрена ядром. А если есть реализация, почему бы ее пользователю не вынести? Мы же не Майкрософт, чтобы полезные фишки прятать.
[QUOTE=cheburator]Т. е. сначала считывается индекс, находятся нужные строки, затем уж считываются строки из таблицы. Насколько я понимаю.[/QUOTE]
Ты вообще представляешь, как выполняется запрос? Вначале строится план, дается на съедение оптимизатору, и только потом начинается непосредственно выборка.
Курсоры - по определению однонаправлены. Не выбрав курсор полностью, нельзя узнать число записей в нем. Соответственно, пока пользователь пялится на первые 25 строк на экране, СУБД может продолжать выборку. Не забывай про реляционную алгебру, занимающую большую часть выполнения запроса.
Много возможностей в СУБД реализовано "на вырост". С данными шутки плохи, и неизвестно, что завтра понадобится при решении задачи. Не будешь же каждый раз ядро переписывать. Тем более, что там сплошная математика - заплаты не прокатят.
Элементарно, чтобы при экспорте/импорте, когда размер таблиц уже известен, выделить сразу экстент нужного размера, соответствующая возможность должна быть предусмотрена ядром. А если есть реализация, почему бы ее пользователю не вынести? Мы же не Майкрософт, чтобы полезные фишки прятать.[/QUOTE]
Видел я многие сотни таблиц, каждый день с ними работаю (например, Управление производственным предприятием 1С v 8.0).
А как такая идея: файл (или файлы) данных условно бьются на страницы (размером, скажем, по 2 Мб), отображаются на память при работе с таблицей целыми окнами. Внутри каждого окна ведется свой собственный список свободной памяти (индексирован по размеру блока и по стартовому адресу). Получается, своего рода "вырост" базы данных (в целом, а не каждой таблицы отдельно) - 2 Мб. Как только требуется место (неважно, для какой таблицы) - выделяется место или в существующей странице, если место там есть, или выделяется новая страница. В общем, суть первоначального вопроса этой темы: зачем выделять отдельные экстенты каждой таблице? Зачем каждую отдельно вести "навырост"? Вести всю БД - чем плохо? Те же справочники, которые редко меняются - ну пусть редко меняются, а если часто создаются/удаляются проводки - пусть часто создаются или удаляются, зачем выводить это на уровень таблицы, если можно вести на уровне БД в целом? Я подумал, что причина тут - не просто "вырост", а преследуется какая-то оптимизационная цель, типа как в кластерах. Видимо, нет. А раз оптимальности это никакой не дает, тем более, повторюсь, зачем выделять аспект "выроста" на уровень таблицы - можно выделять пространство большими блоками на уровне БД в целом, а уж строки какой таблицы туда попадут - дело случая.
[QUOTE=Freeman]
Ты вообще представляешь, как выполняется запрос? Вначале строится план, дается на съедение оптимизатору, и только потом начинается непосредственно выборка.[/QUOTE]
Вот запрос: SELECT * FROM goods WHERE price <= 500, причем price - поле индексированное. Я так понимаю, чтобы система исполнения запросов вообще узнала, какие строки нужно "вытащить" из таблицы, нужно вначале обратиться к индексу, найдя в нем идентификаторы/ссылки/или-что-там-еще этих самых строк. Т. е. выходит, что в любом случае читаем индекс, обрабатываем (ищем в нем), затем читаем собственно строки из таблицы. Какой бы план ни был. А уж какой индекс и как искать - вот это уже дело плана и оптимизатора. Выходит, не совсем понятно, как же так можно читать строки таблицы и индекс одновременно. Если только блоками - нашли первые 500 строк с помощью индекса - создаем параллельный поток, даем ему задание прочесть эти строки, сами в это время ищем следующий блок строк и т. д.
Ты опять-таки мыслишь чисто системно, чего в проектировании делать нельзя - получается системность ради системности.
[QUOTE=cheburator]В общем, суть первоначального вопроса этой темы: зачем выделять отдельные экстенты каждой таблице? Зачем каждую отдельно вести "навырост"?[/QUOTE]
Так можно вести и не навырост. Если точно известно, что размер справочника статичен, можно задать увеличение в 0. Суть в том, что прикладные программисты намного лучше понимают поведение той или иной таблицы, и у них должны быть средства, чтобы это поведение описать.
[QUOTE=cheburator]Я подумал, что причина тут - не просто "вырост", а преследуется какая-то оптимизационная цель, типа как в кластерах.[/QUOTE]
А она и есть. Понять ее - было твоим домашним заданием.
[QUOTE=cheburator]А раз оптимальности это никакой не дает, тем более, повторюсь, зачем выделять аспект "выроста" на уровень таблицы - можно выделять пространство большими блоками на уровне БД в целом, а уж строки какой таблицы туда попадут - дело случая.[/QUOTE]
Если исходить из парадигмы одного файла - согласен. Если из табличных пространств - нет. Впрочем, чисто статичные справочники могут быть и там, и там.
[QUOTE=cheburator]Т. е. выходит, что в любом случае читаем индекс, обрабатываем (ищем в нем), затем читаем собственно строки из таблицы. Какой бы план ни был.[/QUOTE]
Угу. Вот тут-то и надо проявить системное мышление. Создается поток поиска по индексу и поток выборки данных, организуется между ними канал. Продолжать?
К тому же, пример слишком простой, поэтому распараллеливание именно его может оказаться стрельбой из пушки по воробьям. Если же к выборке добавится несколько связываний - уже нет.
[QUOTE=Freeman]А она и есть. Понять ее - было твоим домашним заданием.[/QUOTE]
Это не мое домашнее задание. Это мой первоначальный вопрос. Четкого и ясного ответа, к сожалению, я не услышал.
А если я мышлю не системно (блоки/экстенты), то виноват в этом пресловутый Кайт.
Не припоминаю в Oracle понятие кластера. Это из MS SQL взято?
...
Табличные пространства - способ установить связь на логическом уровне. Из всех СУБД, по-моему, они только в Oracle присутствуют.[/QUOTE]
Первое в оракле присутствует, второе есть не только в нем :)
А по сути заданного вопроса - на него достаточно подробный ответ дает Кен Хендерсон в книге "Профессиональное руководство по SQL Server. Структура и реализация".
З.Ы. Читая Кайта.
"Армяне лучше чем грузины. Чем лучше? Чем грузины!!!" иногда вспоминается :)
Больше преимуществ не вижу.
Вот такие примерно мои рассуждения. Что-то в этом роде я ожидал услышать. Ну что ж, все приходится делать самому :) :(
[QUOTE=cheburator]Таблицы, имеющие первичный ключ, могут организовываться в кластер, т. е. все строки, соответствующие узлу B-дерева индекса, образуют единый блок, или кластер. [/QUOTE]
В кластер (имеется в виду тип сегмента "кластер" БД Oracle - с терминами других БД я не знаком) имеет смысл организовывать таблицы, которые в большинстве случаев используются совместно - этакая денормализация.
То что имелось в виду в вопросе - скорее всего Table Partition (с некоторым натягом). Но для Table Partition нужно определить по какому принципу мы организовываем хранение данных -например данные за 2005 год-в этой партиции, за 2006 - вот в этой.
[QUOTE=cheburator]Как видим, таблица, имеющая первичный ключ, может быть кластерно-организованной.[/QUOTE] Все таблицы могут иметь первичный ключ, однако не все можно организовать в Partition Table (точнеее не все - целесообразно)
[QUOTE=cheburator]К тому же кластер будет скорее всего представлять собой массив, а не связный список, поэтому доступ к элементам будет произвольный, что также ускоряет работу.
[/QUOTE]
А что Вы называете "связным списком"?
[QUOTE=cheburator]Но в большинстве СУБД для всех (!) таблиц используется блочная (экстентная) организация таблиц[/QUOTE]
Блочная организация, на мой взгляд, обусловлена:
1. Блочной организацией носителей данных
2. Необходимостью адресации записи данных в массиве
Больше преимуществ не вижу.[/QUOTE]
Откуда взялась идея, что мы знаем размер строки и этот размер всегда одинаков?
Описаный алгоритм "страничной" организации в-общем то очень похож на существующие - просто разные его части работают на разных уровнях и оперируют разными объектами - блоками, экстентами, строками таблиц и т.п. А идея выделять место для записей различных таблиц (страницу) - не выдерживает никакой критики. (на мой взгляд)