metaclass: (Default)
metaclass ([personal profile] metaclass) wrote2012-10-23 11:27 am

Чувствую, что несу чушь,

но не могу отделаться от ощущения, что с эволюцией баз данных нас очень сильно наебали.
Это по поводу этого: http://plumqqz.livejournal.com/323506.html
Меня очень сильно бесит расхождение технологий: с одной стороны, классические СУБД, с другой NoSQL, с третьей - всякие in-memory распределенные базы, с четвертой - всякие аналитические БД с column storage, сжатием данных и перекосом в сторону чтения типа vertica, sybase iq или забиваторской QD. Плюс еще всякие datomic до которой я никак добраться не могу.

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

[identity profile] metaclass.livejournal.com 2012-10-23 10:33 am (UTC)(link)
insert into table ... values ... returning есть у Firebird, Oracle, Postgresql
SELECT SCOPE_IDENTITY() - mssql
LAST_INSERT_ID() - mysql
IDENTITY_VAL_LOCAL() - db2

[identity profile] plumqqz.livejournal.com 2012-10-23 10:35 am (UTC)(link)
Ну вот видите же.

[identity profile] metaclass.livejournal.com 2012-10-23 11:21 am (UTC)(link)
4 разных, не сводимых друг к другу простой заменой метода. Вижу.

[identity profile] plumqqz.livejournal.com 2012-10-23 11:23 am (UTC)(link)
Ну напишите свой генератор.

[identity profile] metaclass.livejournal.com 2012-10-23 11:31 am (UTC)(link)
1) генерируем ID
2) вставляем запись в таблицу
3) возвращаем ID

Все ли СУБД поддерживают это в одном запросе?
Можно, конечно, сделать тремя запросами с клиента в одной транзакции, только потом стыдно будет на ORM за 1+N запросов псить :)

[identity profile] plumqqz.livejournal.com 2012-10-23 11:36 am (UTC)(link)
Можно, конечно, сделать тремя запросами с клиента в одной транзакции, только потом стыдно будет на ORM за 1+N запросов псить :)
Ну, во-первых, двумя - зачем и куда возвращать уже известный клиенту id лично мне не очень ясно. Во-вторых, это запросы о-очень легкие. В-третьих, незачем генерить ид каждый раз - могут быть проблемы с конкурентностью.

[identity profile] metaclass.livejournal.com 2012-10-23 11:40 am (UTC)(link)
Да, идею понял.

(Anonymous) 2012-10-23 06:05 pm (UTC)(link)
Осталось только научиться генерить такие ID. UUID хороши но блин размер... И правила таких ID? Шел 2012 год, а Степаныч изучал модуль рандом....

[identity profile] maxdz.livejournal.com 2012-10-23 07:13 pm (UTC)(link)
А чем последовательные Id не подходят?

Как сказано оратором выше, одним запросом берётся максимальный Id таблицы (для этого есть специальная аггрегатная функция, которая в ANSI стандарте), а потом в программе генерируется следующий уникальный Id = полученный максимальный Id + 1 и с таким Id делается вожделенный инсерт.

Очень сложно? :)

[identity profile] metaclass.livejournal.com 2012-10-23 07:15 pm (UTC)(link)
Это не работает. Нужно блокировать таблицу целиком на все время выборки и вставки, за что в приличных домах пиздят канделябрами. Ну или поиметь конфликт значений PK.

[identity profile] maxdz.livejournal.com 2012-10-23 07:17 pm (UTC)(link)
Нет никакой выборки. select max(Id) - это запрос, который в индексированной по Id таблице выполняется за миг.

П.С. Ок, атомарности генерации Id и инсерта в таком случае на уровне СУБД не обеспечивается - но атомарность обеспечат инсерты, только через отдельную функцию бизнес-логики и никак иначе.
Edited 2012-10-23 19:22 (UTC)

[identity profile] metaclass.livejournal.com 2012-10-23 07:29 pm (UTC)(link)
Ребе, сейчас сюда придут рабы стагнирующего колхоза и северо-мордорские орки и будут вас травить :)

смотрите картину:
клиент 1: select max(id) from table
клиент 2: select max(id) from table
клиент 1: insert into table(id) values(...)
клиент 2: insert into table(id) values(...) -> PK violation

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

далее, select max(id) не работает мгновенно в MVCC архитектуре - ему нужно выяснить, "какую из версий таблицы я вижу". Надо бы проверить это дело в MSSQL и Postgresql, возможно, там что-то заоптимизировано на эту тему.


В принципе, достаточно красивый вариант предложил крокодил - брать из таблицы секвенсов каждому потоку-клиенту пул ID и затем его расходовать. Если не нужен монотонный рост ID то это вполне ок решение.

[identity profile] maxdz.livejournal.com 2012-10-23 07:33 pm (UTC)(link)
Я написал в P.S. - инсерты должны выполняться только через отдельную функцию, а не напрямую. Это может быть хранимая процедура (но такое не есть хорошо), а может быть функция бизнес-логики.

Когда несколько клиентов имеют возможность делать апдейты/инсерты в БД, напрямую (минуя бизнес-логику, с единообразной организацией/валидацией апдейта/инсерта) - это, в любом случае, нехорошо.

[identity profile] berezovsky.livejournal.com 2012-10-23 07:47 pm (UTC)(link)
в пределе это может тормозить, и надо пользоваться средствами конкретной БД

[identity profile] maxdz.livejournal.com 2012-10-23 07:51 pm (UTC)(link)
Чтобы не тормозило - есть т.н. "аппликэйшн сервера". Но при этом, вынесение всей непосредственной работы с БД на уровень бизнес-логики из клиентов, даёт массу преимуществ, которые с SQL запросами в коде клиентов никак не реализуются.

Да и разница в быстродействии не так уж велика, если вообще (и нивелируется недостатками такой "2-уровневой" архитектуры).

П.С. Единственный легитимный вариант, когда SQL запросы имеют право быть в коде клиента - если клиент работает с выделенной/персональной базой данных, в экслюзивном режиме.
Edited 2012-10-23 19:55 (UTC)

[identity profile] berezovsky.livejournal.com 2012-10-23 08:04 pm (UTC)(link)
Чтобы не тормозило, все производители БД должны объединиться в один и сделать одну нормальную БД. При этом не пользоваться преимуществами монополии и не давать повода клепать новые идиотские БД. По мере того как это будет происходить, усилия будут направляться на улучшение единственной БД, а не размножение новых. Но сейчас действует принцип закулисы "разделяй и властвуй", что и приводит к чувству фрустрации по отношению к эволюции баз.

[identity profile] maxdz.livejournal.com 2012-10-23 08:09 pm (UTC)(link)
Гы-гы. Идеальных/универсальных решений не бывает. Кому-то хочется от БД одного, кому-то иного. Да и конкуренция вынуждает производителей быть в тонусе и делать всё лучшие решения, вместо говна.

Так что, незачем требовать таких глупостей, как единая БД от всех и для всех. :)
Edited 2012-10-23 20:10 (UTC)

[identity profile] berezovsky.livejournal.com 2012-10-23 08:18 pm (UTC)(link)
философия новой эры же :-(

[identity profile] plumqqz.livejournal.com 2012-10-24 06:55 am (UTC)(link)
Ребе, сейчас сюда придут рабы стагнирующего колхоза и северо-мордорские орки и будут вас травить :)
Никто максега травить не будет, не наговаривайте. Грех это. Но вот выражение "Нет никакой выборки. select max(Id) - это запрос, который в индексированной по Id таблице выполняется за миг." мне понравилось - за незамутненность и характерность.

[identity profile] maxdz.livejournal.com 2012-10-25 10:54 am (UTC)(link)
>мне понравилось - за незамутненность и характерность

Ок, не за миг - за одну миллисекунду. Так устроит?

[identity profile] plumqqz.livejournal.com 2012-10-25 11:00 am (UTC)(link)
Были бы вы женщиной - я бы ответил "боже, какая же вы хорошенькая! бросайте это дело к чертовой матери!"
Так как вы не женщина, насколько я понимаю, то высказывание про хорошенькую нужно опустить.

[identity profile] maxdz.livejournal.com 2012-10-25 11:12 am (UTC)(link)
ото и не пустословь, "эксперт"...

(Anonymous) 2012-10-23 06:02 pm (UTC)(link)
Причем очень смешно работает LAST_INSERT_ID() при многопоточности! Офигенно!