metaclass: (Default)
metaclass ([personal profile] metaclass) wrote2010-07-02 02:43 pm

Я в шоке.

Обсуждение одновременного выполнения и чтения двух SQL-запросов в одном коннекте и транзакции (или, упаси Б-г, двух транзакций в одном коннекте) свелось к тому, что НИКТО это не использует. Ну, б-г с ним, что нигде кроме Firebird этого нет, но я всегда считал что операция "ленивым образом перебрать 100500 проводок, параллельно так же ленивым образом вычитывая их детализацию" это самоочевидное действие, такое же как два вложенных цикла, с обработкой списка сущностей в внешнем и списка вложенных сущностей во внутреннем.
Нет, оказывается это не так. Мне предложили все виды извращенной любви с БД - загрузку датасета в память и затем выполнение второго запроса, выполнение джоина и свертку его результатов в граф объектов, и прочая и прочая.
А я тут в святом неведении Олега почитываю на тему fold-like обработки БД и пытаюсь обобщить это на случай доступа к БД из ADO.NET и обработки нескольких вложенных таблиц.

Неудивительно, что NoSQL внезапно оказался настолько популярен. Потому что в умах разработчиков и в большинстве RDBMS аналогов действию "получить сущность и ее подчиненные сущности" просто НЕТ.

[identity profile] zamotivator.livejournal.com 2010-07-02 02:53 pm (UTC)(link)
Кастую крокодила ([livejournal.com profile] plumqqz) в тред.

[identity profile] zamotivator.livejournal.com 2010-07-02 03:03 pm (UTC)(link)
Очень многие говорят, что Perl DBI очень хорош.
Пойти что ли perl выучить ради такого дела, чтобы по достоинству оценить и на другие языки спортировать.

[identity profile] sorhed.livejournal.com 2010-07-02 03:04 pm (UTC)(link)
DBI хорош?

Если DBI считается хорошим (нет, он неплох, конечно, just does its job — но и без изысков) — то я представляю, что там такое в дотнете творится.

[identity profile] zamotivator.livejournal.com 2010-07-02 03:07 pm (UTC)(link)
Я краем глаза ADO как-то раз видел.
Съебался в диком ужасе.

Видать именно поэтому я СУБД пилю, а не под БД разрабатываю.
Психика покорёжена.

[identity profile] sorhed.livejournal.com 2010-07-02 03:09 pm (UTC)(link)
Перл, кстати, всё равно надо знать, конечно. Он, сцуко такое, постоянно пригождается.

[identity profile] metaclass.livejournal.com 2010-07-02 03:16 pm (UTC)(link)
Ад там.

[identity profile] metaclass.livejournal.com 2010-07-02 03:16 pm (UTC)(link)
Даже ОН сказал что надо выполнять запросы по очереди. "Я рыдал полчаса".

[identity profile] plumqqz.livejournal.com 2010-07-02 09:34 pm (UTC)(link)
Дык а как же иначе?
Либо мы только читаем, и тогда нам пофигу, сколько у нас там коннектов.
Либо мы в одной транзакции можем писать из нескольких соединений параллельно, и тогда я даже не знаю что: либо надо разводить транзакции блокировками (и опять какая тогда разница, сколько коннекций - получается просто грязное чтение), либо, если один параллельный процесс в этом соединении может писать туда, куда без завершения транзакции написал другой параллельный процесс этого же соединения, то база просто не будет работать. Не умеет.

[identity profile] metaclass.livejournal.com 2010-07-03 06:08 am (UTC)(link)
Не, тут ситуация такая: даже если мы только читаем - если это делать из разных коннектов/разных транзакций - есть вероятность, что разные запросы увидят разные данные. Если между первой и второй транзакцией всунется какая-нибудь с записью.

[identity profile] plumqqz.livejournal.com 2010-07-03 06:30 pm (UTC)(link)
Стоп. Я, кажется, несколько недопонимаю. Хочется не из двух тредов в рамках одной транзакции писать в базу, а отправить один запрос, потом второй, потом взять данных из первого, потом из второго и так далее?

[identity profile] plumqqz.livejournal.com 2010-07-04 07:46 am (UTC)(link)
Это что, в ADO.NET такое невозможно??! Быть не может.

[identity profile] metaclass.livejournal.com 2010-07-04 07:59 am (UTC)(link)
Возможно через пляски с бубном.
MSSQL - нужно добавить параметр MultipleActiveResultSets=true в строку подключения, проблема, похоже в протоколе сервера. Не рекомендуется в некоторых случаях, по умолчанию выключено.
PostgreSQL - нужно добавить параметр PreloadReader=true в строку подключения, что эффективно убивает весь смысл построчного чтения результатов запросов, т.к. оно при первом обращении высасывает все в память, судя по всему.
Firebird - работает по умолчанию, обычный режим что при доступе через клиентскую либу, что при использовании ADO.NET.

Оракла нету под руками попробовать.

[identity profile] plumqqz.livejournal.com 2010-07-04 08:07 am (UTC)(link)
Что же, остается только сочувствовать.

[identity profile] vromanov.livejournal.com 2010-07-02 03:13 pm (UTC)(link)
В TimesTen аналогично. Возможно это связано с внутреними буферами драйверов.

[identity profile] zamotivator.livejournal.com 2010-07-02 03:17 pm (UTC)(link)
По идее нужно не выёбывацца, а по запросам генерировать типизированные структуры для доступа к базе, а эти структуры пусть будут банальными итераторам по дереву запроса.
Самая простая, дубовая и эффективная структура.
Edited 2010-07-02 15:17 (UTC)

[identity profile] metaclass.livejournal.com 2010-07-02 03:34 pm (UTC)(link)
Вот невозможно!
Я и хочу итератор по дереву, авотхуй.

[identity profile] zamotivator.livejournal.com 2010-07-02 03:35 pm (UTC)(link)
Гм.
Вообще есть синтаксис WITH, RECURSIVE - он для того и нужен, чтобы выборки такие делать.

[identity profile] metaclass.livejournal.com 2010-07-02 03:46 pm (UTC)(link)
Результат все равно реляционный, хоть ты раком там развернись :)

[identity profile] zamotivator.livejournal.com 2010-07-02 05:22 pm (UTC)(link)
А зачем тебе нереляцинный?
Приведи use-case

[identity profile] metaclass.livejournal.com 2010-07-02 05:40 pm (UTC)(link)
Загрузить из БД авизовки с детализацией, произвести над ними хитрожопую обработку и сохранить обратно. При этом не всасывая весь датасет в память.
Вообще, конечно, можно обойтись и непересекающимися запросами в большинстве случаев, но как-то это ограничение, после Firebird и дельфи, где таких проблемы не было, выглядит странно.

[identity profile] zamotivator.livejournal.com 2010-07-02 06:19 pm (UTC)(link)
Что такое авизовка?

[identity profile] metaclass.livejournal.com 2010-07-02 06:25 pm (UTC)(link)
В данном случае - документ с несколькими вложенными записями-строками. А вообще это уведомление о том, что один филиал предприятия должен деньги другому.

[identity profile] zamotivator.livejournal.com 2010-07-03 12:02 am (UTC)(link)
Так это же в таблички преобразуется в итоге

[identity profile] gds.livejournal.com 2010-07-02 03:51 pm (UTC)(link)
я всегда думал, что можно сколько угодно мультиплексировать выборки. Казалось естественным. Может поэтому я нормально к СУБД отношусь.

У Олега -- iteratees -- не помогут достичь нужного, если драйвера не умеют. Или что вообще хочется?

[identity profile] metaclass.livejournal.com 2010-07-02 03:57 pm (UTC)(link)
Именно мультиплексировать выборки.

[identity profile] gds.livejournal.com 2010-07-02 04:25 pm (UTC)(link)
если я правильно понимаю и хочется мультиплексировать выборки из двух различных сессий, выбирая нужные записи то оттуда, то отсюда, то iteratees не особо нужны тут, имхо. Обычные потоки/последовательности подойдут так же, а то и лучше. Замечу, не ленивые значения индуктивных типов, как в х-е, а честные коиндуктивные, как например в окамле всяком. (не знаю, как в этом вашем дотнете с этим дела обстоят)

[identity profile] nivanych.livejournal.com 2010-07-05 08:30 am (UTC)(link)
Замечу, что в хаскеле уже давненько рекомендуется коиндукция, может быть, и замаскированно.
Но что уж точно, так это в чистом виде ленивые списки обширно применять я не порекомендую.
А если программка не должна долго работать (типа сервера), тогда пофигу, лишь бы отработала.

[identity profile] gds.livejournal.com 2010-07-05 08:36 am (UTC)(link)
не, всё правильно говоришь, но попробуй объяснить это "обезьяне с монадой", которая всё в списки пихает, потому что это гламурненько и потому что фолды няшные.

[identity profile] metaclass.livejournal.com 2010-07-05 08:52 am (UTC)(link)
Шо такое "коиндукция"?

[identity profile] nivanych.livejournal.com 2010-07-05 09:50 am (UTC)(link)
Меня уже более 5 месяцев теребят более 5 человек, чтобы я описал, наконец, что это такое ;-)
Индукция по начальной алгебре выдаёт стрелку (катаморфизм) к любой другой алгебре, и внутри работает, как обобщённые на любые алгебраические типы фолд.

Алгебра, это стрелка F a -> a, где a, это носитель алгебры, F - сигнатура.
Почему так? А просто.
Cамый распостранённый пример алгебры, это когда F является функтором каждого объекта категории в пары объектов этого же типа, и получим (a,a) -> a, то есть, отображение пар элементов типа a (ну или n-ок, в чуть более общем случае) в само a.
Вот только _начальная_алгебра_ для такого функтора, это уже бесконечное бинарное дерево, и оно нереализуемое, поскольку, в функторе мы не указали что-то типа a*a + 1, где *, это категорное произведение (пара-тупл), + это копроизведение (навроде вариантного типа), 1 - терминальный объект.
То есть, указывая +1, мы даём возможность экземплярам этого типа быть единицей или же далее деревом. В хацкеле это тип data Q = BinTree (Q,Q) | Leaf, а изначально было просто data Q = BinTree (Q,Q).

Но F может быть более сложным функтором, и даже, всего лишь, полиномиальные (это которые можно реализовать в хацкеле) уже могут дать любопытного.

Коалгебра, это стрелка a -> F a.
На том же примере получим a -> (a,a), и в этом случае, мы можем даже обойтись таким функтором, без всяких дополнений вроде + 1, поскольку для коиндукции это уже не требуется.
Что ж такое коиндукция. А это штука, даже немного более простая, чем индукция.

Если начальную алгебру можно сопоставить с наименьшей неподвижной точкой, то терминальную коалгебру с наибольшей. Это какбе "наибольшее", что можно построить по данной сигнатуре.

Стрелка (анаморфизм) от любой коалгебры к терминальной представляет из себя выбор конкретной коалгебры, которую содержит эта терминальная, то есть, по сути, твою функцию с сигнатурой a -> F a (коалгебру) превращает в значение типа _терминальной_ коалгебры, давая возможность обозвать все такие функции элементами одного типа терминальной коалгебры.
Можно даже сказать, что терминальная коалгебра, это интерфейс, а конкретные коалгебры с анаморфизмами (коиндукция) и есть реализации этого интерфейса. При этом, носитель коалгебры играет роль эдакого "состояния", и зачастую, не может быть показан тому, кто использует коалгебру, уже как экземпляр терминальной, и состояние может только участвовать в операциях.
Приведу пример.
Возьмём более сложный функтор F a = a*b + 1.
Возьмём коалгебры для этого функтора a -> a*b + 1.
То есть, все функции такого типa для любых a и b.
Анаморфизм (коиндукция) из такой функции делает некий экземпляр терминальной коалгебры с неким носителем, и мы получаем функцию term -> term*b + 1, причём, к term мы "прикасаться" не можем, а только использовать его, доставая "конец" в виде 1, нечто типа b и новое "состояние".

Резюмируя, получим, что в категории могут существовать для каких-то функторов (обычно, полиномиальных, то есть, состоящих из произведения, копроизведения и экспоненты, то есть, типов a->b).
Если они существуют, тогда у нас есть некая операция, которая для любого такого функтора даёт возможность построит стрелку от любой коалгебры (функция с сигнатурой a -> F a) до специального объекта-состояния, представляющего из себя все такие коалгебры для данного функтора. И после есть операция над этой терминальной коалгеброй, при которой мы не можем получить "состояние", а оно осталось в той коалгебре, от которой мы проводили стрелку, ну и всякой побочное, зависящее от функтора. То есть, терминальные коалгебры для фунтора F a = a*a, в обещем-то, штука бесполезная, так как, "состояние a" нам в явном виде не достать.

Есть ещё такое терминальные F,G-диалгебры, которые F zю -> G zю, в них уже можно напрямую и очень близко эмулировать обычные интерфейсы, (например) полагая F = (zю,a,b,c), G = (zю,d,e,f). Правда, именно такое можно и коалгебрами сделать, полагая отображение zю -> (a->b->c->(zю,d,e,f)).

Очень сумбурно объяснил, категорно было бы гораздо лучше, но сходу сделать понятным не получилось, поэтому, держи около-попсово-программистский стиль ;-(
Так же, с позором признаюсь, что не раскрыта тема монад и алгебр, комонад и коалгебр, "arrows" и диалгебр...
Как-нибудь, я соберусь сделать хорошее, годное объяснение...

[identity profile] weissefly.livejournal.com 2010-07-07 02:15 pm (UTC)(link)
Многаумныхслоф. Сами-то как думаете, кому-нибудь понятней стало ? Лучше напишите, где про это можно прочитать в непопсовом виде.

[identity profile] nivanych.livejournal.com 2010-07-08 04:59 am (UTC)(link)
Для тех, кто знает основы, вполне возможно, что стало понятнее.
Прочитать можно очень много, где.
Материалов дохрена, гуглится запросто.
Что-то рекомендовать даже и не стоит, проще читать и спрашивать.
Например, в category_theory. На моё взгляд, категории тут очень нужны.

Ну, таки можно порекомендовать тов. Varmo Vene, вот страничка с его работами ->
http://www.cs.ut.ee/~varmo/papers/index.html

И в частности, более-менее, неплохое объяснение с примерами на Haskell ->
Categorical programming with inductive and coinductive types
http://www.cs.ut.ee/~varmo/papers/thesis.pdf

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

Как более серьёзное, советую читать Фрейда, он довольно тонко разбирается в теме.
Далее, посмотреть всё подряд, что найдётся, про диалгебры (и Фрейдовые и F,G-диалгебры).
Про F,G-диалгебры есть книжка аж от 86 года от тов. Tatsuya Hagino
http://www.tom.sfc.keio.ac.jp/~hagino/index.html.en
Первая книжка, это попытка построение категорного языка.
Вторая, это построение немного необычной типизированной лямбды на этой идее.

Если и лямбда-подобное, где в качестве кирпичиков используются даже end/coend'ы.
Очень много всего.

[identity profile] weissefly.livejournal.com 2010-07-10 11:50 am (UTC)(link)
Спасибо, почитаю. Если смогу распутать, с чего следует начинать.

[identity profile] nivanych.livejournal.com 2010-07-10 01:03 pm (UTC)(link)
Если хоть немного знать Haskell и основы теории категорий, то вполне должен прочитаться Varmo Vene.
Фрейда зовут Peter Freyd (чтобы было проще искать).

[identity profile] molnij.livejournal.com 2010-07-02 06:13 pm (UTC)(link)
Разумеется оракл это умеет.. Просто в этом ключе я не думал коментировать )
Кстати, а как тогда в Net делается показ master-child выборок если там нельзя паралельно два запроса запустить?

[identity profile] metaclass.livejournal.com 2010-07-02 06:26 pm (UTC)(link)
Сначала грузятся в память (Dataset) все мастер-записи, а потом все child-записи, затем объединяются по описанным связям. Есть специальный класс, который это умеет. Но оверхед у этого дикий.

[identity profile] norguhtar.livejournal.com 2010-07-03 04:27 am (UTC)(link)
А все это от того что с СУБД лучше не работать процедурно. Она по своей сути декларативна. Так что, то что вы предлагаете необходимо только в определенных условиях. К примеру у нас дохлый канал и обработка возможна только строго последовательна и обрабатывается внешним алгоритмом.

[identity profile] enternet.livejournal.com 2010-07-04 07:33 pm (UTC)(link)
Для решения такой задачи:
1) на ib/fb я, помнится, просто денормализовал результат
2) на оракле можно возвращать вложенные курсоры. Как-то пробовал, геморрой это.
3) на MSSQL я возвращаю XML. это просто и удобно в обработке.

[identity profile] ennor.livejournal.com 2010-07-05 12:09 am (UTC)(link)
Это ты, случаем, не про MSDataShape? Они, вроде, на него забили давно.

Вообще, можно на самом деле так вопрос поставить - если тебе надо одновременно более двух датасетов, то зачем выносить их обработку за пределы СУБД? Я сильно сомневаюсь, что хоть один клиент сумеет соединить мастер-деталь в себе быстрее, чем база данных. Ему же еще индексы строить придется, или там хеш-таблицу.

Но это уже потенциальная переработка архитектуры может потребоваться - если изначально все писалось в стиле 1С, а теперь надо все ускорить и вообще сделать по уму, то конечно упс...

И кстати да, XML (там, где он есть) никто не отменял.

[identity profile] blacklion.livejournal.com 2010-07-05 09:11 am (UTC)(link)
Потому что в умах разработчиков и в большинстве RDBMS аналогов действию "получить сущность и ее подчиненные сущности" просто НЕТ.
JOIN'ы, блин! но то это и реляционка!

[identity profile] metaclass.livejournal.com 2010-07-05 09:12 am (UTC)(link)
Ага, я знаю множество примеров того, что люди JOIN-ов боятся. Потому что когда-то у каждого сервера с ними были свои заморочки.

Но в данном случае join тут не поможет.

[identity profile] fraks-nsk.livejournal.com 2010-07-07 06:15 am (UTC)(link)
А что за кайф в базе если джойны не юзать? БОльшая часть цимеса побоку оказывается.