Здравствуйте, AndrewVK, Вы писали:
AVK>О первичных ключах: AVK>1) Допустимо ли требование обязательного наличия первичного ключа?
+
AVK>2) Допустимо ли требование несоставного первичного ключа?
+
AVK>3) Допустимо ли требование первичного ключа определенного типа?
+
AVK>4) Допустимо ли требование первичного ключа типа GUID?
—
AVK>О расширяемости: AVK>Что должно быть расширяемо в сабже?
AVK>О keysets: AVK>1) Допустимо ли встраивание этой механики в движек БД.
+ AVK>2) Достаточно ли самого простого варианта, или нужна возможность подкрузки в кейсет части данных?
не совсем понятно, какая догрузка имеется в виду? AVK>3) Нужна ли многостадийная загрузка или подгрузка в 2 стадии — кейсет и остальные данные? Или может еще какой вариант?
3-й вариант — загрузка каждого элемента или группы элементов по требованию (это имелось ввиду?).
AVK>О запросах подробнее: AVK>1) Необходим ли SQL или любой другой текстовый декларативный язык запросов?
скорее да, чем нет... ибо удобно, да и опять же, возможно захочется тулзы делать. В принципе, можно SQL прикрутить как внешннюю либу AVK>2) Что лучше — выборки или навигационный способ(курсоры).
Оба хороши, каждый для своего AVK>3) Что лучше — декларативный sql-like синтаксис или функциональный стиль?
будет свой язык???
AVK>О метаданных: AVK>1) Допустим ли отказ от специфичных для БД метаданных в пользу метаданных, встроенных в платформу?
вон оно как... скорее да, чем нет. AVK>2) Допустим ли (и возможен ли?) полный отказ от нетипизированных данных (нетипизированных на уровне строки) при работе с БД?
трудный вопрос... А как насчет проекций и отчетов? AVK>3) Должны ли типы хранится в БД вместе с данными?
минимальная схема+аттрибуты — да. Вроде как дублирование с кодом (вопросы выше), с одной стороны. С другой стороны — хоть какая-то защита от несогласованных изменений в коде и базе.
AVK>О деплойменте: AVK>Нужна ли поддержка автоматической реструктуризации данных при смене типов, встроенная в движек?
Вряд ли это легко без специального инструментария по смене типа. Т.е. мы поменяли имя и тип колонки/поля. Если эти действия не трекить, но непонятно, какая колонка куда поменялась... В общем, если речь идет о дотнет (насколько я понял), то типы и результирующие сборки для подобной БД нужно разрабатывать в некоем своем инструменте, с поддержкой такой реструктуризацией. Скорее, не в движек это надо встраивать, а в инструмент разработки. AVK>Какие еще аспекты БД было бы интересно рассмотреть с точки зрения описанной задачи?
Политики владения/связи. Привязать сюда же GC для зависимых данных (почему бы и нет?)
Здравствуйте, AndrewVK, Вы писали:
AVK>P.S. AVK>О транзакциях: AVK>1) Оптимистичные или пессимистичные? AVK>2) Нужны ли вложенные транзакции? AVK>3) Можно ли обойтись без транзакций вовсе или вынести их из движка БД на уровень библиотеки?
Если делать только пессимистичные (а только они и имеют право называться настоящими ), то можно на уровень либы.
А эмуляцию оптимистичных пускай прикладной код делает на своих кешах.
Здравствуйте, Merle, Вы писали:
AVK>>1) Оптимистичные или пессимистичные? M>А какая разница, если БД однопользовательская?
А почему бе не рассмотреть вариант мини-сервера приложений, где используется такая легковесная БД?
AVK>>2) Нужны ли вложенные транзакции? M>Нет.
Спорно. Особенно, если будет предоставлена возможность императивно обрабатывать данные.
AVK>>3) Можно ли обойтись без транзакций вовсе или вынести их из движка БД на уровень библиотеки? M>Нет, Атомарность изменений и устойчивость, пусть лучше БД обеспечивает.
В случае in-process понятие БД расплывается, то бишь граница БД и прикладного кода чисто условная. Почему бы не рассмотреть вариант базовых классов транзакций и механизмов по ее работе?
Здравствуйте, vdimas, Вы писали:
AVK>>4) Допустимо ли требование первичного ключа типа GUID? V>-
Традиционный вопрос — почему?
AVK>>2) Достаточно ли самого простого варианта, или нужна возможность подкрузки в кейсет части данных? V>не совсем понятно, какая догрузка имеется в виду?
Обычно в кейсете содержаться только первичные ключи. Однако для некоторых алгоритмов может обязательно понадобится какое нибудь поле. Тогда выгоднее выгрузить в кейсет часть данных.
AVK>>3) Нужна ли многостадийная загрузка или подгрузка в 2 стадии — кейсет и остальные данные? Или может еще какой вариант? V>3-й вариант — загрузка каждого элемента или группы элементов по требованию (это имелось ввиду?).
Да.
AVK>>1) Необходим ли SQL или любой другой текстовый декларативный язык запросов? V>скорее да, чем нет... ибо удобно, да и опять же
В чем удобство?
V>, возможно захочется тулзы делать.
Тому, кому захочется и флаг в руки.
AVK>>2) Что лучше — выборки или навигационный способ(курсоры). V>Оба хороши, каждый для своего
Они взаимозаменямы, так что основным должен быть какой то один.
AVK>>3) Что лучше — декларативный sql-like синтаксис или функциональный стиль? V>будет свой язык???
Нет.
AVK>>2) Допустим ли (и возможен ли?) полный отказ от нетипизированных данных (нетипизированных на уровне строки) при работе с БД? V>трудный вопрос... А как насчет проекций и отчетов?
Проекции типизированные, отчеты — проблема тех, кто эти отчеты будет рисовать. Опять же — рефлекшен и полиморфизм никто не отменял.
AVK>>Нужна ли поддержка автоматической реструктуризации данных при смене типов, встроенная в движек? V>Вряд ли это легко без специального инструментария по смене типа. Т.е. мы поменяли имя и тип колонки/поля. Если эти действия не трекить, но непонятно, какая колонка куда поменялась...
Это элементарно решается привязыванием ко всем элементам метаданных уникального идентификатора. Если идентификатор другой, значит это другая колонка. Если нет — значит та же.
V> В общем, если речь идет о дотнет (насколько я понял), то типы и результирующие сборки для подобной БД нужно разрабатывать в некоем своем инструменте, с поддержкой такой реструктуризацией.
Совсем не обязательно.
AVK>>Какие еще аспекты БД было бы интересно рассмотреть с точки зрения описанной задачи? V>Политики владения/связи. Привязать сюда же GC для зависимых данных (почему бы и нет?)
Да вобщем особых проблем нет. Я как то даже в рпабочей системе такую штуку делал. Другое дело имеет ли смысл такое встраивать в БД?
Здравствуйте, vdimas, Вы писали:
V>Желательны оба варианта. В первом варианте неплохо бы получить "сырой" интерфейс на какие-нить row set-ы, чтобы помимо декларативного SQL иметь возможность для императивных циклических алгоритмов.
А зачем этот вариант нужен для однопользовательской БД?
AVK>>3) Описание метаданных
V>Не понятен вопрос. Речь идет о возможном РАСШИРЕНИИ стандартных метаданных? (стандартные — ну там тип поля и ограничения, типа nullable, участие в индексе или ограничения в виде SQL)
Нет никаких стандартных.
AVK>>4) Способ формирования запросов
V>Если in-proccess, то доп. через "сырые" интерфейсы доступа к данным.
Здравствуйте, GlebZ, Вы писали:
GZ>Курсор как таковой мало интересен и малофункицонален и неудобен по сравнению с тем же IEnumerator.
А по моему курсор и должен имплементировать IEnumerator. То есть это одно и тоже.
GZ>Насчет ключей есть другая думка. В реляционных базах данных есть несколько типов join. Один из них построен на хеше. То есть, у нас есть два отношения. Один из них меньше другого. При join, база данных строит хеш-таблицу RID по маленькому списку, и затем просто находит значения для большого списка и соединяет. Очень действенный механизм. Поскольку уже никто не возражает что ключ должен быть глобально уникальным для БД, и синтетическим, то вполне можно использовать именно хеширование. Кроме того, это даст нам путь быстрого нахождение одного объекта.
Во-во. Точно. Индексы по первиному ключу надо делать хэш-таблицей, а не деревом.
Здравствуйте, AndrewVK, Вы писали:
S>>А вот БД как абстрактный класс даст возможность применять намного больше фантазии и инструменты для отражения различных классов но такую БД.
AVK>Ага, а заодно потратить несколько лишних мегабаксов на проект.
Зря ты так считаешь. Конфигуратор аля 1С со своими набором классов не стот мегабаксы, но в отличие от 1С возможно будет возможно расширение за счет новых классов. Они тоже свою БД сделали правда ориентированную на SQL а зря, хотя и универсально.
и солнце б утром не вставало, когда бы не было меня
Здравствуйте, stalcer, Вы писали:
S>Во-во. Точно. Индексы по первиному ключу надо делать хэш-таблицей, а не деревом.
К тебе тот же вопрос — как обеспечить малое количество дисковых операций при добавлении или удалении элементов? Стандартная техника с бакетами, используемая в нетовских хештаблицах для диска мало подходит.
Здравствуйте, AndrewVK, Вы писали:
AVK>>>И при чем здесь функциональная форма? Ты декларативную привел. GZ>>Перепиши в функциональных терминах, будет то же самое. Проблема существует. AVK>Может быть. Но какое это имеет отношение к функциональному стилю?
Ну поробуй построить построитель запросов для почтовика типа outlook.
У нас есть письма. У нас есть адресная книга. Все это показывается в едином окне. У пользователя существуют рычаги того, как ему показывать, какие поля из письма или адресной книги, сделать фильтр по любому полю, отсортироваться по любому полю.
AVK>>>Неа. Я уже совершенно потерялся и не могу понять, что ты хочешь доказать. GZ>>Что keyset не нужен. AVK>В ООБД? Возможно. А вот в реляционных иногда очень даже.
Только не keyset. Повторюсь, неэффективно. К тому же еще я не уверен что при проекции вообще мы будем знать по какому id адресоваться.
AVK>А вот именно этот вопрос я и задавал. Ответов я знаю несколько. Можно анализировать IL, можно отказаться от лямбд в операции проекции, можно использовать LINQ.
Linq при сложной проекции функциклирует в read only. Анализировать IL — не понял. Отказаться можно, но тяжко. Больно бенефит хороший.
Фактически мы можем сохранять любой объект имеющий все not null поля(PK — также not null поле). Но тут еще один вопрос. Информация о реальном объекте находится в запросе а не в типе, и зависит от запроса и метаданных. В случае если мы изменим запрос, или подредактируем not null, у нас типы могут просто полететь в программе. Насколько это хорошо, сомневаюсь.
Еще проблема есть другая. Мы делаем такой запрос(пишу в SQL):
select a.*, b.id from a outer join b on (a.id=b.id)
И при этом b.id является not null полем, которое не всегда подгружается. Чую здесь будут проблемы в типах.
Вобщем лучше этим пока не заморачиваться, и запретить лямбду в проекции. Либо сделать дополнительно ручник. То есть ручное сохранение.
GZ>>Легко. Но надо сначало со структурой хранения. Хеш функция ведь должна по чему-то адресоваться. AVK>Структура хранения — страничный файл.
Ну смотри,
1-32 — байт относительный адрес страницы и относительный адрес значения в странице.
Например, у нас 8 килобайтная страницы. Каждый физический указатель — 8 байт. На странице 8кБ/8=1024 значений. Как результат для получения значения в странице hash&0x3FF. У нас осталось 22 бита с помощью которых мы будем адресовать страницы. Что в общем случае значит — адресацию 31 миллиардов значений. Число вполне достойное и не настольной системы.
Однако при этом надо думать о несовпадении удаленных и созданных значений индексов. Вот на это, мы и употребим оставшихся 32 бита. То есть будет некоторый счетчик уникальности hash значений. Вероятность совпадения 1/(2*32) — практически космическая, в особенности для настольных систем. В данном случае, я бы подумал даже о том, как сохранить информацию о типе. Я думаю, она очень пригодится на программном уровне. Допустим, отнять биты у адресации, и вероятности.
Единственный недостаток. Страницы не могут уменьшаться. Единственное когда они могут уменьшиться, операция типа truncate table или удаление. В случае уменьшения, адресация теряется.
Что касается создания, удаления. В данном случае предлагается использовать такой же механизм, как и для страниц таблиц. Только там есть степень заполненности, а нам нужно просто иметь bitmap, есть пустое или нет. Фактически поиск будет ограничен поиском в рамках страницы.
Здравствуйте, AndrewVK, Вы писали:
AVK>К тебе тот же вопрос — как обеспечить малое количество дисковых операций при добавлении или удалении элементов? Стандартная техника с бакетами, используемая в нетовских хештаблицах для диска мало подходит.
А какая разница? Вот, например, надо удалить 10 случайно выбранных объектов. И деревянный индекс и хэш-табличный ты будешь изменять в 10-и местах. И никакой локальности не будет.
Так? Или я не прав?
Здравствуйте, stalcer, Вы писали:
S>Здравствуйте, AndrewVK, Вы писали:
AVK>>К тебе тот же вопрос — как обеспечить малое количество дисковых операций при добавлении или удалении элементов? Стандартная техника с бакетами, используемая в нетовских хештаблицах для диска мало подходит.
S>А какая разница? Вот, например, надо удалить 10 случайно выбранных объектов. И деревянный индекс и хэш-табличный ты будешь изменять в 10-и местах. И никакой локальности не будет. S>Так? Или я не прав?
Почти да. Фрагментация сильно влияет на чтении, и значительно меньше на записи. В случае, если мы ведем лог, то мы удерживаем измененые блоки в памяти, и сбрасываем в лог изменения последовательно. Сброс основных данных идет в определенной время(нехватка памяти, комп ни фига не делает, или просто по таймеру). Сброс можно сделать последовательным, с меньшей фрагментацией.
Здравствуйте, Merle, Вы писали:
M>Это и есть нормальное решение, здесь не надо сложнее. Для поиска по таким текстам B+ все равно бесполезен, здесь надо все равно движек поиска по блобам отдельно подключать. А ключа размером с килобайт для B+ — за глаза.
Скажи мне. Вот MSSQL2000 позволяет создавать таблицы где записи с varchar по метаданным больше чем 8 кБ. При сохранении данных более 8 килобайт выдается ошибка. Ты когда-нибудь этой фичей пользовался?
Здравствуйте, GlebZ, Вы писали:
GZ>Скажи мне. Вот MSSQL2000 позволяет создавать таблицы где записи с varchar по метаданным больше чем 8 кБ.
Нет, 2000 не позволяет (он просто обрезает остаток), позволяет 2005й... Но уже 2000й позволял иметь начальную часть БЛОБ-а на основнй странице, а остальное хранить в отдельном месте.
Но при чем тут это?
Здравствуйте, GlebZ, Вы писали:
GZ>Ну поробуй построить построитель запросов для почтовика типа outlook.
Нафига оно мне? Построитель запросов для outlook выходит за рамки собственно БД. В отличие от внутрипрограммного доступа такая фича нужна далеко не всегда и сильно завязана на предметную область.
AVK>>>>Неа. Я уже совершенно потерялся и не могу понять, что ты хочешь доказать. GZ>>>Что keyset не нужен. AVK>>В ООБД? Возможно. А вот в реляционных иногда очень даже. GZ>Только не keyset. Повторюсь, неэффективно.
Можешь повторяться сколько хочешь, только это не аргумент. На практике я с его использованием получал огромный выигрышь во времени реакции системы на действия пользователей, особенно когда в самом запросе есть тяжелые джойны.
GZ> К тому же еще я не уверен что при проекции вообще мы будем знать по какому id адресоваться.
Тут все очень просто — надо проектировать запросы такими, чтобы знать все что необходимо.
GZ>Linq при сложной проекции функциклирует в read only.
BLToolkit тоже. На реальных проектах это не сильно беспокоит. Пойми, я не хочу сейчас обсуждать OR mapper и мне не очень нравится идея встраивать его в БД. А вне меппера ни о каких модификациях проекций речи даже не идет.
GZ>Фактически мы можем сохранять любой объект имеющий все not null поля(PK — также not null поле).
PK это readonly-поле. Что я точно знаю, так это то что ни в одной реальной задаче мне не понадобилось модифицировать значение первичного ключа.
GZ> Но тут еще один вопрос. Информация о реальном объекте находится в запросе а не в типе, и зависит от запроса и метаданных.
Только в том случае, если на уровне БД есть полиморфизм. В реляционных БД никакого полиморфизма нет.
GZ>
GZ>select a.*, b.id from a outer join b on (a.id=b.id)
GZ>
GZ>И при этом b.id является not null полем, которое не всегда подгружается. Чую здесь будут проблемы в типах.
Какие? Ты пойми — задача создания нужного типа и задача формирования проекции на него целиком на плечах прикладного программиста. Вот он пусть и разруливает. Не надо пытаться наворотить на движек БД все возможные задачи — чем он проще, тем качественнее.
GZ>1-32 — байт относительный адрес страницы и относительный адрес значения в странице. GZ>Например, у нас 8 килобайтная страницы. Каждый физический указатель — 8 байт. На странице 8кБ/8=1024 значений.
Каких значенией? Хеш-кодов?
GZ> Как результат для получения значения в странице hash&0x3FF.
Уже непонятно.
GZ> У нас осталось 22 бита с помощью которых мы будем адресовать страницы.
Еще менее понятно. Страница имеет свой собственный адрес, глобальный в пределах файла.
GZ>Однако при этом надо думать о несовпадении удаленных и созданных значений индексов. Вот на это, мы и употребим оставшихся 32 бита. То есть будет некоторый счетчик уникальности hash значений. Вероятность совпадения 1/(2*32) — практически космическая, в особенности для настольных систем. В данном случае, я бы подумал даже о том, как сохранить информацию о типе. Я думаю, она очень пригодится на программном уровне. Допустим, отнять биты у адресации, и вероятности.
Что то ты явно пропустил. И, главное — в хеше значения обязаны содержаться упорядоченно. Следовательно, если очередной PK нарушает порядок следования, следует переупорядочивать хеш на диске. Это очень дорого и как от этого избавиться ты так и не сказал.
GZ>Что касается создания, удаления. В данном случае предлагается использовать такой же механизм, как и для страниц таблиц.
Нельзя. В В+ дереве, в чем его прелесть, упорядоченность поддерживается автоматически. Использовать расщепление страниц для модификации хеш-таблицы не выйдет — там нужна линейная упорядоченность. Либо придется хранить в памяти соответствие между страницами хеш-индекса и порядком следования, что не очень здорово.
Здравствуйте, stalcer, Вы писали:
AVK>>К тебе тот же вопрос — как обеспечить малое количество дисковых операций при добавлении или удалении элементов? Стандартная техника с бакетами, используемая в нетовских хештаблицах для диска мало подходит.
S>А какая разница?
Разница самая обыкновенная — для того чтобы работала хеш-таблица хеши должны быть линейно упорядоченны. Как обеспечивается это в памяти я знаю, а вот как обеспечить это на диске пока не ясно.
Здравствуйте, GlebZ, Вы писали:
S>>А какая разница? Вот, например, надо удалить 10 случайно выбранных объектов. И деревянный индекс и хэш-табличный ты будешь изменять в 10-и местах. И никакой локальности не будет.
GZ>Почти да. Фрагментация сильно влияет на чтении, и значительно меньше на записи.
Я не про фрагментацию, а про локальность. Т.е. если я удаляю 10 обектов, то мне придется исправить индекс в 10 местах. И вероятность того, что эти 10 мест будут далеко друг от друга (на разных страницах) — велика. И не потому, что присутствует фрагментация, а потому, что я взял 10 случайных объектов.
Абсолютно та же ситуация и на чтение.
И я не виже разницы в этом плане между деревом поиска и хэш таблицей.
Я утверждаю, что для того чтобы найти физический адрес объекта (тупла) по индексу необходимо обратиться как минимум к одной странице индекса. Для того, чтобы сделать изменения данных, затрагивающие индекс — нужно изменить как минимум одну страницу индекса.
Если изменений в транзакции много, то и страниц будет потенциально много, так как локальности — нет.
Здравствуйте, Merle, Вы писали:
GZ>>Скажи мне. Вот MSSQL2000 позволяет создавать таблицы где записи с varchar по метаданным больше чем 8 кБ. M>Нет, 2000 не позволяет (он просто обрезает остаток), позволяет 2005й... Но уже 2000й позволял иметь начальную часть БЛОБ-а на основнй странице, а остальное хранить в отдельном месте. M>Но при чем тут это?
А притом, что это практически одинаковое предложение. Сделать задачу такой, что когда нибудь она может стрельнуть. А то что стрельнет, по закону подлости — обязательно.
Здравствуйте, GlebZ, Вы писали:
GZ>А притом, что это практически одинаковое предложение.
Давай без практически. Ты что, действительно разницы не видишь?
Не имеет практического смысла делать ключ для B+ длиннее килобайта, вне зависимости от длинны самого поля.
GZ> Сделать задачу такой, что когда нибудь она может стрельнуть.
Здесь нечему стрелять. Вообще.
GZ> А то что стрельнет, по закону подлости — обязательно.
Приведи мне пример задачи, где пригодился бы поиск по B+ с ключем длиннее килобайта.