NoSQL vs RDBMS: Too may FOREIGN KEYs
Сижу делаю очередную опердень, и наткнулся на печаль: таблицы содержат сильно больше внешних ключей и вообще структуры/связей (которые в FB основаны на индексах), чем собственно данных. Это после адекватной нормализации и отображения требуемой для расчетов структуры на базу данных. Типа того, что в таблице, где хранятся суммы, 4 поля, из них 3 - это разного рода ссылки на сущности "налогооблагаемый объект", "период расчета", "период уплаты", и одно поле - собственно сумма.
Причем раньше у меня было чисто технологическое ограничение - чем больше таблиц, тем больше приходилось писать вручную sql-скриптов, маппингов "таблицы-объекты", запросов для работы с таблицами. Я поэтому особо не нормализовал, шел по пути типа "нужно 12 месяцев - заводим 12 полей, нужно 4 квартала - заводим 4 поля". А сейчас, во первых, с кодогенератором это ограничение исчезло, а во вторых, 4 квартала и 12 месяцев превратились в "список периодов, диктуемый каждый отчетный год министерству по налогам и сборам Червем из астрального мира".
Т.е. если мы идем по пути "много структур данных и мало кода", который нам в голову диктует функциональщина, то отражение этого дела в RDBMS превращает ее в невероятно запутанный граф, в котором связи занимают больше места чем данные. Если бы это был NoSQL, а наши данные имели явно заметную тенденцию объединятся в объекты (т.е. работа с записями из связанных таблиц ведется всегда вместе), то мы бы просто ложили в NoSQL объект в виде xml/json/любой структурированный текст.
Бинарное представление в NoSQL было бы сильно эффективнее текста в плане размера и обработки, но, во первых для него нужна статическая типизация, схема и тому подобное (чтобы сериализация/десериализация были эффективными), и обработку этого должна делать СУБД, т.к. я совершенно не испытываю желания это все делать.
Кроме того, как уже неоднократно писалось: RDBMS работает эффективнее, т.к. ее данные, условно говоря - это последовательность бинарных записей одинаковой длины, хождение по которым - это +-длина записей. А всякая бинарщина и xml - это парсеры, сериализация и прочий плохо взаимодействующий с кэшами процессоров и выделением памяти тупизм.
В моем случае это все не применимо в принципе - 99% требуемой от разрабатываемого модуля функциональности уже реализовано в виде "Firebird+Универсальный толстый клиент на дельфи", основная обработка ведется SQL запросами и кодом внутри FB. Всунуться сюда с чем-то, хоть отдаленно похожим на NoSQL, невозможно. Т.е. постулат: NoSQL == разработка с нуля, что на данный момент неприемлемо никак.
Но вообще, даже если мы вместо чистого NoSQL придумаем какой-то хитрожопый вариант типа "статически типизированные объекты в бинарном виде", индексы по внутренностям этих объектов для оптимизации запросов, функциональщину в качестве языка запросов, то все равно останется проблема с тем, что объекты теперь не представимы в виде записей постоянной длины (хотя сейчас больше проблема с дисковым i/o, чем с нагрузкой на проц) и что все равно как-то придется идентифицировать объекты независимо от их физического расположения - а это означает опять ID, опять индексы, сопоставляющие ID и физическое расположение, опять связи по этим ID и прочая и прочая.
Причем раньше у меня было чисто технологическое ограничение - чем больше таблиц, тем больше приходилось писать вручную sql-скриптов, маппингов "таблицы-объекты", запросов для работы с таблицами. Я поэтому особо не нормализовал, шел по пути типа "нужно 12 месяцев - заводим 12 полей, нужно 4 квартала - заводим 4 поля". А сейчас, во первых, с кодогенератором это ограничение исчезло, а во вторых, 4 квартала и 12 месяцев превратились в "список периодов, диктуемый каждый отчетный год министерству по налогам и сборам Червем из астрального мира".
Т.е. если мы идем по пути "много структур данных и мало кода", который нам в голову диктует функциональщина, то отражение этого дела в RDBMS превращает ее в невероятно запутанный граф, в котором связи занимают больше места чем данные. Если бы это был NoSQL, а наши данные имели явно заметную тенденцию объединятся в объекты (т.е. работа с записями из связанных таблиц ведется всегда вместе), то мы бы просто ложили в NoSQL объект в виде xml/json/любой структурированный текст.
Бинарное представление в NoSQL было бы сильно эффективнее текста в плане размера и обработки, но, во первых для него нужна статическая типизация, схема и тому подобное (чтобы сериализация/десериализация были эффективными), и обработку этого должна делать СУБД, т.к. я совершенно не испытываю желания это все делать.
Кроме того, как уже неоднократно писалось: RDBMS работает эффективнее, т.к. ее данные, условно говоря - это последовательность бинарных записей одинаковой длины, хождение по которым - это +-длина записей. А всякая бинарщина и xml - это парсеры, сериализация и прочий плохо взаимодействующий с кэшами процессоров и выделением памяти тупизм.
В моем случае это все не применимо в принципе - 99% требуемой от разрабатываемого модуля функциональности уже реализовано в виде "Firebird+Универсальный толстый клиент на дельфи", основная обработка ведется SQL запросами и кодом внутри FB. Всунуться сюда с чем-то, хоть отдаленно похожим на NoSQL, невозможно. Т.е. постулат: NoSQL == разработка с нуля, что на данный момент неприемлемо никак.
Но вообще, даже если мы вместо чистого NoSQL придумаем какой-то хитрожопый вариант типа "статически типизированные объекты в бинарном виде", индексы по внутренностям этих объектов для оптимизации запросов, функциональщину в качестве языка запросов, то все равно останется проблема с тем, что объекты теперь не представимы в виде записей постоянной длины (хотя сейчас больше проблема с дисковым i/o, чем с нагрузкой на проц) и что все равно как-то придется идентифицировать объекты независимо от их физического расположения - а это означает опять ID, опять индексы, сопоставляющие ID и физическое расположение, опять связи по этим ID и прочая и прочая.
no subject
12 месяцев - 12 полей - это как???
no subject
create table sometable(
ID
...
M1 numeric(18,4),
M2 numeric(18,4),
...
M12 numeric(18,4)
);
Хорошо в том случае, если не нужно делать запросы вида "найти месяцы в которых сумма была меньше заданной" и когда суммы гарантированно есть каждый месяц.
Иначе лучше сделать отдельную таблицу (ID,Month,Total)
no subject
А зачем тут ID?
Разве Month не однозначно идентифицирует что за месяц имеется в виду, или возможны разные Total с одинаковым Month?
no subject
no subject
no subject
no subject
no subject
Объектные можно. Вот как маппить функциональные не понятно.
no subject
no subject
Офигенно удобно, когда по большей части они скачут по управляющей структуре. Один черт количество SQL запросов будет сравнимо что при чистом SQL что при ORM, а мозгоклюйства на порядок меньше.
no subject
no subject
no subject
no subject
no subject
no subject
матыселекты и пишутся и читаются человеком, ну а при ORM ваще нет о чём волноваться.А вот ежели одна "логически" табличка (читаемая с одной формы или поиска) рассыпалась по 14-ти разным, и при этом 2 тысячи юзверей одновременно этот запрос юзают - прямая путя в денормализацию, запихнул всё в плоскую таблицу (ну или материализовывать) и будет полегче, и плевать на кошерность базы, ибо апгрейд железа для "нормализованной" базы начинает кусаться.
no subject
cемиэтажные селекты и пишутся и читаются человеком
и
вот ежели одна "логически" табличка (читаемая с одной формы или поиска) рассыпалась по 14-ти разным
считаете что 7 джойнов - допустимо, а 14 - не допустимо?
no subject
При большой нагрузке - допустимо, но нежелательно.
no subject
Как-то думал над гибридом sql+nosql: по умолчанию все однотипные сущности хранятся в таблице (id:number * serialized:blob). Отдельно хранится "схема" -- что в serialized соответствует чему (типы, т.е.). Запросы писать на sql (да пофиг, на чём), но всё, что касается условий над аттрибутами/связями, преобразовывать в get_mytype_attr(blob, 'my_attr'). То есть, выполняться оно будет, как факт. Далее, как ключевой момент идеи, научиться переносить аттрибуты из сериализованного представления в отдельные столбцы. Переносить -- либо вручную, когда очевидно, что и как будет использоваться, либо по результатам профайлинга. Перенос аттрибута можно оформить полупрозрачным образом: посмотреть, умеет ли субд экономно хранить ещё один блоб, содержащий почти всегда нуллы, и на каждую "миграцию аттрибута" в фоновом режиме заполнять второй блоб (с учётом того, что могут проапдейтить то, что уже перенесено: заставить все update обнулять значение второго блоба). Или же блокировать любой доступ к таблице, добавлять столбец, модифицировать блоб in-place.
Хотя, прикидываю, в большинстве случаев такое нафиг не нужно. С другой стороны, если бы я использовал nosql в больших количествах, то, зная преимущества реляционок, был бы не прочь иметь такое решение.