metaclass: (Default)
metaclass ([personal profile] metaclass) wrote2010-07-02 07:04 am

Как же удолбут.

Тема "сессий" и "транзакций" при подключениях к различным базам данных судя по всему является очередным потаенным вуду для разработчиков. Причем даже для разработчиков самих БД и драйверов доступа к ним.

Иначе я не могу объяснить тот факт, что в некоторых серверах невозможно открыть одновременно две транзакции в одном соединении. Или то, что из трех ADO.NET провайдеров (Firebird, MSSQL, Postgresql) одновременно открыть два SQL запроса в одном соединении и читать одновременно из них - можно только в Firebird, два остальных ругаются типа "уже открыт DataReader".

Ну вот вопрос как в ADO.NET ленивым образом (не загружая в память) прочитать список сущностей из БД, и для каждой сущности прочитать вложенные для нее?
Ну всегда обычное решение было - цикл по одному DataReader, из него берем некое поле, подсовываем его значение в параметр второй команде, выполняем ExecuteReader и пытаемся читать во вложенном цикле. В Firebird работает, в других хрен.

PS: В Npgsql есть параметр PreloadReader=true, который позволяет обойти это ограничение и который не рекомендуется использовать, т.к. он грузит весь DataReader в память и смысл ленивой итерации теряется. И написано, что это ограничение - by design, упомянуто в доке на ADO.NET.

По моему, архитекторов ADO.NET надо убить, это же идиотизм клинический.

[identity profile] norguhtar.livejournal.com 2010-07-02 07:55 am (UTC)(link)
Честно говоря у меня есть ощущение, что вы хотите странного. Я вот ситуацию того что больше одной транзакции в одном соединении открыть нельзя не считаю вполне нормальным.

[identity profile] metaclass.livejournal.com 2010-07-02 08:01 am (UTC)(link)
Ну с транзакциями хрен с ним - все равно уже давно никто не использует длительные транзакции в БД, все занимаются извращениями в стиле "загрузили в одной короткой, час юзер редактировал, затем сохранили в другой короткой", эффективно убивая вообще весь смысл транзакций.

Но вот невозможность читать из двух SQL запросов одновременно - это какой-то бред тяжкий, имхо.

[identity profile] norguhtar.livejournal.com 2010-07-02 08:11 am (UTC)(link)
И как вы себе представляете одновременное чтение из двух SQL запросов в одном подключении? С моей точки зрения это приведет к неоправданному усложнению кода как со стороны сервера так и со стороны клиента.

[identity profile] metaclass.livejournal.com 2010-07-02 08:19 am (UTC)(link)
А в чем сложность то? Всю жизнь в дельфи+firebird так делали. Препарим два запроса, один выполняем, читаем в цикле, внутри цикла выполняем другой, читаем во вложенном цикле.
В API это выглядит как создание запроса, получение его хендла и затем использование этого хендла первым параметром во всех функциях(prepare, fetch, close).

[identity profile] norguhtar.livejournal.com 2010-07-02 08:39 am (UTC)(link)
В реализации. В случае соединения разделение транзакций и получения и отправки данных ложится на tcp/ip. В случае же одного соединения, надо будет городить это разделение внутри соединения, что приведет к усложеннию кода как со стороны клиента, так и со стороны сервера.

[identity profile] metaclass.livejournal.com 2010-07-02 08:22 am (UTC)(link)
Встречный вопрос: как без этого функционала сделать ленивую обработку двух таблиц - основной и подчиненной. Какое-нибудь элементарное задание вроде "обработать 10 млн проводок с детализацией"

[identity profile] norguhtar.livejournal.com 2010-07-02 08:41 am (UTC)(link)
use connection pool luke!
Я вот вообще этим не запариваюсь. У меня JPA это все делает.

[identity profile] volodymir-k.livejournal.com 2010-07-02 09:03 am (UTC)(link)
Это и называется быдлокодинг. Если программер работает на БД с 20 записями и верит, что 10 млн строк это то же самое.

Попробуйте продумать алгоритм расчёта зарплат для 20 тыс.рабочих согласно белорусскому законодательству, желательно в пределах 3 часов. Могу примерно припомнить исходные таблицы:
- журналы рабочего времени по видам работ
- тарифы по видам работ
- таблица совместителей
- накопленные налоги по сотрудникам за последние 2 года
- справочник МРОТ по месяцам
- справочник налогов по месяцам
- справочник размеры пособий по уходу за ребенком
- выплаченные пособия за ребенком
- больничные листы
... где-то ещё штук 20 таблиц, забыл уже.

[identity profile] norguhtar.livejournal.com 2010-07-02 09:16 am (UTC)(link)

Это и называется быдлокодинг. Если программер работает на БД с 20 записями и верит, что 10 млн строк это то же самое.

Это называется вы не знаете чем, я занимаюсь :)


Попробуйте продумать алгоритм расчёта зарплат для 20 тыс.рабочих согласно белорусскому законодательству, желательно в пределах 3 часов.

Я вам могу встречную задачу по тарификации услуг доступа к сети предложить. Какое это имеет отношение к JPA и connection pool?

[identity profile] volodymir-k.livejournal.com 2010-07-02 01:38 pm (UTC)(link)
> Какое это имеет отношение к JPA и connection pool?

Вы всё еще не догадались???
Я намекаю, что программер должен не высасывать сразу все данные в память, а читать кусками; для этого и нужно понимание, какие соединения делают какие транзакции, вместо тупого использования connection pool.

Я вообще не понимаю, как можно в системах batch обработки использовать пулы. Поток вычисления-то один. Разве что тупо брать соединения, когда левая пятка в коде захочет?

[identity profile] norguhtar.livejournal.com 2010-07-02 04:46 pm (UTC)(link)

Я намекаю, что программер должен не высасывать сразу все данные в память, а читать кусками; для этого и нужно понимание, какие соединения делают какие транзакции, вместо тупого использования connection pool.

Вы шо считаете меня идиотом да? Вообще в JPA для ограничения идиотов по умолчанию фетчится только первая 1000 строк. Да и я не фетчу 1000 строк при таких обновлениях.



Я вообще не понимаю, как можно в системах batch обработки использовать пулы. Поток вычисления-то один. Разве что тупо брать соединения, когда левая пятка в коде захочет?

В случае batch достаточно и одного подключения. Как бе у меня подразумевается обычно:

Одно подключение для длинных транзакций
N-подключений для множества коротких одновременных транзакций

[identity profile] vaddimka.livejournal.com 2010-07-03 12:49 am (UTC)(link)
мне кажется, вы не совсем понимаете всю концепцию connection pool'ов.
пул никак не связан со способом фетча данных.
можно читать результаты тяжелого запроса в одном подключении, дергать множество мелких - в другом. то же самое с несколькими транзакциями
Ребе, вероятно, смутило что ранее он использовал некое API, которое менеджило подключения к БД за него; с другой стороны все решается достаточно примитивным врэппером.

[identity profile] metaclass.livejournal.com 2010-07-03 06:10 am (UTC)(link)
Оно ничего не менеджило, это нативная фича сервера и клиентской либы. Соединение там в норме одно на весь сеанс работы.

[identity profile] vaddimka.livejournal.com 2010-07-03 12:27 pm (UTC)(link)
А, круто. Интересно как там interleaving реализован.

[identity profile] metaclass.livejournal.com 2010-07-02 09:08 am (UTC)(link)
Интересно, как в JPA этот вопрос обходят. Подозреваю, что таки исключительно непересекающимися фетчами результатов.

[identity profile] norguhtar.livejournal.com 2010-07-02 09:18 am (UTC)(link)
Где так и есть. Только вот ленивые запросы там с осторожностью надо использовать иначе можно на больших объемах словить пачку запросов в базу.

[identity profile] norguhtar.livejournal.com 2010-07-02 10:13 am (UTC)(link)
Кстати да. Я тут подумал. А что мешает использовать join запрос?

[identity profile] metaclass.livejournal.com 2010-07-02 10:20 am (UTC)(link)
И что это будет? Денормализованный датасет типа "на каждую запись в детализации (коих over 9000) повторяем запись-владелец"?

[identity profile] norguhtar.livejournal.com 2010-07-02 10:27 am (UTC)(link)
Да. А дальше обрабатываем. В чем собственно проблема? В том что с этим не удобно работать?

[identity profile] metaclass.livejournal.com 2010-07-02 10:29 am (UTC)(link)
В том что это маразм, очевиднейший. Сначала делаем декартово произведение, денормализуем, сосем по не самому быстрому каналу на клиента увеличенный по сравнению с нужным результат, а потом его нормализуем обратно, закатывая солнце вручную.
Проще уж на сервере все обработать тогда, ничего на клиента/миддлварь не вытаскивая.

[identity profile] norguhtar.livejournal.com 2010-07-02 11:47 am (UTC)(link)
Если у вас обрабатываются все данные это самый быстрый способ их получить и обработать. Если выборочно относительно того какие данные в первой таблице, то можно делать отдельный ленивый select. Опять же никто offset и limit не отменял.

[identity profile] vp.livejournal.com 2010-07-02 10:37 am (UTC)(link)
Не, это явный перебор.
Приемлемо ТОЛЬКО в случае, когда ну вообще никаких средств не осталось..

[identity profile] norguhtar.livejournal.com 2010-07-02 11:53 am (UTC)(link)
Если вы обрабатываете данные в обоих таблицах это самый правильный и быстрый вариант для получения данных. Если вы обрабатываете выборочно данные во второй подчиненной таблице, то можно использовать запросы. Иначе у вас будет пиздец-пиздец по производительности. Как раз из-за перманентного дерганья второй таблицы.

[identity profile] metaclass.livejournal.com 2010-07-02 11:58 am (UTC)(link)
Пиздец-пиздец будет только в кривых серверах, которые не умеют запросы препарить и держать отпрепаренными. Таблица по всякому будет в кэше сервера, если запрос не закрывать каждый раз - оно летает, проверено.
Другое дело что, судя по всему, ADO.NET это корректно делать не умеет, т.к. затачивалась под кривые сервера, коих большинство.

[identity profile] norguhtar.livejournal.com 2010-07-02 12:29 pm (UTC)(link)
Вообще время работы первого запроса будет ниже чем суммарное время второго. Вообщем как делать сильно зависит от того что делать. Ну и к слову JPA умеет из join который я привел разворачивать два объекта, так что с точки зрения удобства тут все в порядке.

[identity profile] vp.livejournal.com 2010-07-02 03:32 pm (UTC)(link)
ADO ж вообще задумывался как обобщенный интерфейс к БД. Вот скорее всего они и привели его к наименьшему общему знаменателю, выкинув такого рода фичи серверов, которые не обобщаются.

[identity profile] molnij.livejournal.com 2010-07-02 11:25 am (UTC)(link)
Если такое "подключение" умеет единственно - выполнять ровно один запрос, то лично у меня возникает вопрос в его смысле. Можно смело выкинуть подключение оставив запрос\команду\etc упростив многоэтажный пирог абстракций доступа к данным и не потерять ничего.

[identity profile] norguhtar.livejournal.com 2010-07-02 04:36 pm (UTC)(link)
Последовательно оно умеет сколько угодно. Параллельно надо вписывать уже фабрику подключений.