Здравствуйте, TK, Вы писали:
TK>Только, вот сопровождаемость этого дела (если запихнуть всю логику в БД) может упасть точно так же...
Всё зависит от того, как написаны запросы. Современные СУБД предоставляют вполне вменяемые средства декомпозиции запросов, и при должной квалификации разработчика получается все более-менее нормально. А некомпетентный разработчик и в апп-сервере наколбасит неподдерживаемого кода — только в путь.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
TK>>Только, вот сопровождаемость этого дела (если запихнуть всю логику в БД) может упасть точно так же... S>Всё зависит от того, как написаны запросы. Современные СУБД предоставляют вполне вменяемые средства декомпозиции запросов, и при должной квалификации разработчика получается все более-менее нормально. А некомпетентный разработчик и в апп-сервере наколбасит неподдерживаемого кода — только в путь.
У меня, например, та же проблема. В моей предметной области на SQL все плохо ложится — операции типа "взять следующий элемент и сравнить с двумя предидущими", например, делаются через Ж. Так что проще писать тупой императивный код, работающий с объектами.
И тут кэш просто рулит. Реальные цифры: "отчет" (если быть точным — подготовка данных для группы отчетов) выполнял 5112 SQL-операторов и занимал 51 секунду времени. Включили кэш, после загрузки данных в него — отчет стал занимать 300 миллисекунд (там что потом его сериализация для отдачи клиенту дольше занимает). Разница по времени — больше чем на два порядка.
Кстати, объектная база (которая работает в качестве "персистентного кэша" на узлах-хабах) выполняет тот же отчет за 5 секунд.
Здравствуйте, Ivan Danilov, Вы писали:
S>>Не надо так делать. Читайте классику. Хранимая процедура обхода дерева пишется на FB на раз-два. Прочитайте для начала статьи на RSDN, посвяшенные хранению иерархических структур. ID>Я в курсе пользы хранимых процедур и активно их использую. Статьи читал, и не только их.
В таком случае, не вполне понятно ваше желание использовать множество запросов к СУБД в рамках одного клиентского запроса. Как правило, такие решения возникают на базе использования навигационного доступа к данным, что есть Великое Зло.
ID>Разворор вроде сейчас идет о кэшировании, а не о поддержке транзакций?
Как это? Разговор начался ровно с проблем синхронизации. Я надеюсь, связь транзакций с синхронизацией очевидна? ID>В контексте кэша: ID> Изоляция (Isolation) — это и было проблемой. Но если сделать по копии данных для каждого потока — и она отпадает.
Гм. Я не знаю специфики вашего приложения, но как правило, 1 инстанс кэша на поток — это очень дорого.
При мелкой гранулярности проблема упирается в наполнение кэша. Грубо говоря, за каждым объектом нужно сбегать в базу данных, причем отдельным запросом. Кэширование результатов запроса целиком в этом смысле значительно дешевле.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, Ivan Danilov, Вы писали: ID>>А хранить нужные данные в памяти даст не тот же самый результат? S>Нет, не тот же. S>В отличие от данных в памяти, запрос автоматически выполняется с нужным уровнем изоляции и нет нужды вручную обеспечивать ACID.
Про ACID в моем случае здесь: Re[16]: Multithreading в Application server layer
По-моему все нормально.
ID>> За тем исключением, что так они уже разобраны и готовы, а результаты запроса еще нужно обработать перед передачей на клиента. S>Непонятно, что значит "разобраны и готовы". Клиенту вряд ли передают набор бизнес-объектов; скорее речь идет о построении какого-то сериализованного представления — HTML/XML/PDF/XLS. Ну так вот генерация этого представления из удобным образом сформированного датасета ничуть не дороже, чем по бизнес-объектам, лежащим в памяти.
Угу, построение дерева по плоскому датасету для расчета статистических значений тоже ничего не требует. В принципе, можно переложить это дело на клиента — тогда и правда будет ничуть не дороже. Но если начальство захочет отдельный тип прав "Просмотр статистики" — то возможна ситуация, когда сами данные недоступны, а статистика доступна. И передавать на клиента уже нельзя.
Честно говоря, преимущества хранения копии данных в кэше я вижу (если ресурсов хватает). А вот преимущества подхода "оставить все на СУБД" довольно расплывчаты пока что. Потому и спорю
S>Если хочется что-то покэшировать, то лучше кэшировать именно отчет. См. напр. серверные генераторы отчетов (Crystal, MS SQL Server Reporting Services и др.).
Зачем кэшировать отчеты, которые строятся раз в неделю?
Здравствуйте, Ivan Danilov, Вы писали:
ID>Сопоставима. Там везде каналы толстые, т.е. локалка, поделенная на 2 домена.
При чем тут толщина канала? Речь о среднем времени, которое апп-сервер затрачивает на обработку запроса. Если, к примеру, это время измеряется в десятках миллисекунд, то лантентность канала между апп-мервером и СУБД можно особо во внимание не принимать.
ID>Хм. Как Вы написали чуть выше, имеет смысл учитывать только латентность. Она таким образом сокращается ровно вдвое — на запрос к СУБД (если посчитать каналы к серверу и клиенту одинаковыми).
Я написал, что, возможно, имеет смысл учитывать латентность. А возможно и не имеет.
ID>А если еще учесть специфику данных — иерархическое дерево в БД, что влечет за собой большое количество запросов для обхода — выигрыш может быть даже и больше. Ведь так я все дерево сразу собираю на апп-сервере, а так его по частям придется выдирать из СУБД (например, если нужен отчет по ветке со всеми детьми).
Можешь организовать в апп-сервере локальную БД и синхронизировать ее по мере надобности.
ID>Делал. Загрузка всей базы и распихивание по business entities занимает около минуты, может быть чуть-чуть больше.
50М распихивать минуту? Что то какое то экстремально больлшое время у тебя получилось.
Здравствуйте, Cyberax, Вы писали:
C>Смотри что за приложение.
О чем я и пишу..
C>Скорость извлечения данных из локального кэша обычно в тысячи раз быстрее даже простого обращения к БД.
Вопрос в другом — нужна ли эта тысяча.
C>Если у нас есть много мелких запросов — выигрыш может быть весьма значителен.
А может и не быть, даже скорее всего не будет. С другой стороны, выигрыш будет еще больше, если кешировтаь не голые данные, а уже ближе к конечному пользователю, скажем, если это веб-приложение, то кешировать уже отрендеренные веб-страницы.
Вот поэтому я и говорю, что надо сначало понять что кешировать и зачем, а потом уже бросаться это делать.
Здравствуйте, Ivan Danilov, Вы писали:
ID>Я не имел в виду открыть новый Connection, я имел в виду именно задержки при передаче запроса/ответа.
Задержки именно на передачу — минимальны.
ID>А какая разница, куда поднимет ее сама СУБД?
Она поднимает ее практически туда, куда хочешь ты...
ID> О_о Предположим, что время обработки любого запроса СУБД — 0.
Не надо предполагать. Надо взять и померять и только после того как выяснилось чторезультат не устраивает — вкрячивать кешь в то место, где он окажется наиболее эффективным и наименее затратным в реализации. Или просто зарпос переписать или пересмотреть логику работы с отчетами.
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, TK, Вы писали:
TK>>Только, вот сопровождаемость этого дела (если запихнуть всю логику в БД) может упасть точно так же... S>Всё зависит от того, как написаны запросы. Современные СУБД предоставляют вполне вменяемые средства декомпозиции запросов, и при должной квалификации разработчика получается все более-менее нормально. А некомпетентный разработчик и в апп-сервере наколбасит неподдерживаемого кода — только в путь.
В FireBird появились человеческие средства, сравнимые по удобству сопровождения с нормально написанным кодом на C#?
В прошлой версии, написанной на Delphi/Interbase, вся логика была как раз завязана на SP. Такое спагетти... Хотя писал не я, предшественника я понимаю — языка СУБД просто не хватает, чтобы нормально все реализовать.
Вот, сейчас переписываю.
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, Ivan Danilov, Вы писали:
ID>>Я в курсе пользы хранимых процедур и активно их использую. Статьи читал, и не только их. S>В таком случае, не вполне понятно ваше желание использовать множество запросов к СУБД в рамках одного клиентского запроса. Как правило, такие решения возникают на базе использования навигационного доступа к данным, что есть Великое Зло.
Я описывал худший случай. Просто очень не хочется на каждую задачу писать хранимку — я и так в них начинаю путаться уже
Естесственно, что полный обход дерева рекурсивно не выполняется — оно же до завтра работать будет
ID>>Разворор вроде сейчас идет о кэшировании, а не о поддержке транзакций? S>Как это? Разговор начался ровно с проблем синхронизации. Я надеюсь, связь транзакций с синхронизацией очевидна?
Угу. Меня мучил вопрос изолированности данных именно в кэше.
S>Гм. Я не знаю специфики вашего приложения, но как правило, 1 инстанс кэша на поток — это очень дорого.
А зачем мне весь кэш копировать? Как правило, пользователь работает только с небольшим набором бизнес-объектов за раз. Да и то, если не требуется редактирование — можно всем выдавать один и тот же объект. Операции же редактирования вообще довольно редкие (сравнительно с чтением) и для них сделать по копии нужных объектов не будет накладно.
S>При мелкой гранулярности проблема упирается в наполнение кэша. Грубо говоря, за каждым объектом нужно сбегать в базу данных, причем отдельным запросом. Кэширование результатов запроса целиком в этом смысле значительно дешевле.
Так вот собственно, кэшированние всей БД — частный случай кэширования результатов запроса целиком
И бегать за объектами в БД придется только если их кто-то обновил, т.е. при сбросе кэша.
Здравствуйте, Ivan Danilov, Вы писали:
ID>Возможно, кто-то встречался с интересными паттернами или просто поделится опытом — где лучше всего решать проблемы синхронизации в сервере приложений?
ID>Можно линк на статью/best practices etc.
ID>P.S. Так как вопрос о стоящей задаче все равно кто-то задаст — она в общих описана здесь: Re[4]: Глобальные переменные
IB wrote: > C>Скорость извлечения данных из локального кэша обычно в тысячи раз > быстрее даже простого обращения к БД. > Вопрос в другом — нужна ли эта тысяча.
Эрм... Ускорение в тысячу раз — ненужная вещь? Вы, случаем, не в Intel
работаете?
> C>Если у нас есть много мелких запросов — выигрыш может быть весьма > значителен. > А может и не быть, даже скорее всего не будет.
Будет. Абсолютно точно — сам проверял не раз. Из-за банального
отсутствия round-trip'а до базы данных.
> С другой стороны, выигрыш > будет еще больше, если кешировтаь не голые данные, а уже ближе к > конечному пользователю, скажем, если это веб-приложение, то кешировать > уже отрендеренные веб-страницы.
А тут у нас проблем с когерентностью данных — не всегда просто понять
когда надо менять страницу, в случае изменения данных.
> Вот поэтому я и говорю, что надо сначало понять что кешировать и зачем, > а потом уже бросаться это делать.
Естественно. Серебряных пуль я не предлагаю.
Здравствуйте, Cyberax, Вы писали:
C>Эрм... Ускорение в тысячу раз — ненужная вещь?
Не ужели ты очередной маньяк от производительности? Не разочаровывай меня..
C>Будет. Абсолютно точно — сам проверял не раз.
Ты проверял на своих, довольно узких задачах.
C> Из-за банального отсутствия round-trip'а до базы данных.
Ходить до базы в тысячу раз медленнее чем не ходить? У тебя БД ручным тормозом оборудована?
C>А тут у нас проблем с когерентностью данных — не всегда просто понять когда надо менять страницу, в случае изменения данных.
Тут у нас проблем, как правило, не больше чем с когерентностью БО, а зачастую даже меньше. Впрочем, опять-таки от задачи зависит.
C>Естественно. Серебряных пуль я не предлагаю.
А я что-то такое уж было заподозрил.. )
Hello, Cyberax!
You wrote on Tue, 21 Aug 2007 07:59:14 GMT:
TK>>> Только, вот сопровождаемость этого дела (если запихнуть всю TK>>> логику в БД) может упасть точно так же... S>> Всё зависит от того, как написаны запросы. Современные СУБД S>> предоставляют вполне вменяемые средства декомпозиции запросов, и S>> при должной квалификации разработчика получается все более-менее S>> нормально. А некомпетентный разработчик и в апп-сервере S>> наколбасит неподдерживаемого кода — только в путь. C> У меня, например, та же проблема. В моей предметной области на SQL C> все плохо ложится — операции типа "взять следующий элемент и C> сравнить с двумя предидущими", например, делаются через Ж. Так что C> проще писать тупой императивный код, работающий с объектами.
Здравствуйте, YК, Вы писали:
C>> У меня, например, та же проблема. В моей предметной области на SQL C>> все плохо ложится — операции типа "взять следующий элемент и C>> сравнить с двумя предидущими", например, делаются через Ж. Так что C>> проще писать тупой императивный код, работающий с объектами. YК>Это чистой воды OLAP. Зачем тут SQL вообще?
Это никакой не OLAP, даже близко. У меня, в основном, проблемы связаны с учетом рабочего времени и составлением расписания.
Hello, Cyberax!
You wrote on Tue, 21 Aug 2007 09:36:22 GMT:
C>>> У меня, например, та же проблема. В моей предметной области на C>>> SQL все плохо ложится — операции типа "взять следующий элемент C>>> и сравнить с двумя предидущими", например, делаются через Ж. C>>> Так что проще писать тупой императивный код, работающий с C>>> объектами. YК>> Это чистой воды OLAP. Зачем тут SQL вообще? C> Это никакой не OLAP, даже близко. У меня, в основном, проблемы C> связаны с учетом рабочего времени и составлением расписания.
Судя по описанию, проблемы связаны с использованием неподходящего инструмента. Запросы вроде "взять следующий элемент и сравнить с двумя предыдущими" делаются на MDX элементарно.
Здравствуйте, Cyberax, Вы писали: C>У меня, например, та же проблема. В моей предметной области на SQL все плохо ложится — операции типа "взять следующий элемент и сравнить с двумя предидущими", например, делаются через Ж.
Интересно. В MS SQL это работало достаточно эффективно начиная примерно с 2000 версии. Впрочем, я согласен с тем, что есть класс задач, плохо выражающийся в терминах реляционной алгебры. Пока что принадлежность данной конкретной задачи к этому классу неочевидно.
C>Так что проще писать тупой императивный код, работающий с объектами.
Ну... "Проще" — не всегда значит "лучше". В таких случаях меня настораживают вопросы типа "все хорошо, но как мне...". Ну то есть человек воспользовался неким супер-подходом (например, Lazy load) для красивого и простого решения какой-нибудь задачи. А потом у него вылезает какая-нибудь мелкая проблемка, навроде когерентности кэшей, и я начинаю подозревать вероятность появления совершенно чудовищных костылей, которые полностью нивелируют простоту и красоту этого замечательного подхода.
C>И тут кэш просто рулит. Реальные цифры: "отчет" (если быть точным — подготовка данных для группы отчетов) выполнял 5112 SQL-операторов и занимал 51 секунду времени. Включили кэш, после загрузки данных в него — отчет стал занимать 300 миллисекунд (там что потом его сериализация для отдачи клиенту дольше занимает). Разница по времени — больше чем на два порядка.
Ничего удивительного. Я в свое время занимался оптимизацией отчетов, которые уже были написаны на SQL. Но их писали индусы, имеющие самое отдаленное представление о планах запросов и механике SQL Server, поэтому нудное и кропотливое переписывание SQL выигрывало тоже от порядка до двух. Просто благодаря выбору правильного порядка join/group by. C>Кстати, объектная база (которая работает в качестве "персистентного кэша" на узлах-хабах) выполняет тот же отчет за 5 секунд.
Как правило, банальное переписывание взрослого отчета с клиппера на MS SQL замедляет его в несколько раз. Потому что курсоры в клиппере реализованы существенно более оптимально. А вот переписывание его с нуля на том же MS SQL, аккуратная раздача индексов, и прочие методы традиционной медицины творят просто чудеса.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Ivan Danilov, Вы писали: ID>В FireBird появились человеческие средства, сравнимые по удобству сопровождения с нормально написанным кодом на C#?
На моей памяти, хватало и средств Interbase 6.0. ID>В прошлой версии, написанной на Delphi/Interbase, вся логика была как раз завязана на SP. Такое спагетти... Хотя писал не я, предшественника я понимаю — языка СУБД просто не хватает, чтобы нормально все реализовать.
А чего именно не хватает? ID>Вот, сейчас переписываю.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
IB wrote: > C>Эрм... Ускорение в тысячу раз — ненужная вещь? > Не ужели ты очередной маньяк от производительности? Не разочаровывай меня..
А, угадаю еще раз — в Microsoft?
> C>Будет. Абсолютно точно — сам проверял не раз. > Ты проверял на своих, довольно узких задачах.
Не таких уж узких. Почти всегда performance от кэша выигрывает.
> C> Из-за банального отсутствия round-trip'а до базы данных. > Ходить до базы в тысячу раз медленнее чем не ходить? У тебя БД ручным > тормозом оборудована?
Нет. Типичный roundtrip по сети до базы — около миллисекунды, причем это
еще при хороших условиях.
Сколько за это время можно достать и склонировать объектов из hash-карты
в локальной памяти ты можешь посчитать сам.
> C>А тут у нас проблем с когерентностью данных — не всегда просто понять > когда надо менять страницу, в случае изменения данных. > Тут у нас проблем, как правило, не больше чем с когерентностью БО, а > зачастую даже меньше. Впрочем, опять-таки от задачи зависит.
А еще бывают GUI-клиенты
YК wrote: > YК>> Это чистой воды OLAP. Зачем тут SQL вообще? > C> Это никакой не OLAP, даже близко. У меня, в основном, проблемы > C> связаны с учетом рабочего времени и составлением расписания. > Судя по описанию, проблемы связаны с использованием неподходящего > инструмента. Запросы вроде "взять следующий элемент и сравнить с двумя > предыдущими" делаются на MDX элементарно.
У меня нет хороших и красивых упорядоченых последовательностей, по
которым можно строить кубики. "Предидущий" элемент зависит от каждого
конкретного параметра отчета.
Представь себе расписание — нужно его автоматически составить. Могут
быть констрейнты типа "человек не должен работать более двух дней подряд
в одном подразделении" или "работать только в один из выходных через две
недели". Попробуй на досуге записать второе условие в SQL. Причем таких
параметров штук 20 (и постоянно добавляются).
Sinclair wrote: > Интересно. В MS SQL это работало достаточно эффективно начиная примерно > с 2000 версии. Впрочем, я согласен с тем, что есть класс задач, плохо > выражающийся в терминах реляционной алгебры. Пока что принадлежность > данной конкретной задачи к этому классу неочевидно.
Какие именно? Естественно, не имеется в виду ссылка на два предидущих
ряда запроса — там логические сущности, которые тоже надо вычислять.
Мы пробовали это делать — оказывается, что MSSQL и Oracle часто тупо
сливают императивному коду из-за того, что не могут использовать
мемоизацию и другие оптимизации. А борьба с помощью хинтов —
изнурительное занятие.
> C>Так что проще писать тупой императивный код, работающий с объектами. > Ну... "Проще" — не всегда значит "лучше". В таких случаях меня > настораживают вопросы типа "все хорошо, но как мне...". Ну то есть > человек воспользовался неким супер-подходом (например, Lazy load) для > красивого и простого решения какой-нибудь задачи. А потом у него > вылезает какая-нибудь мелкая проблемка, навроде когерентности кэшей, и я > начинаю подозревать вероятность появления совершенно чудовищных > костылей, которые полностью нивелируют простоту и красоту этого > замечательного подхода.
Поэтому мы используем транзакционный, кластерный кэш и двухфазный коммит
(который не нужен для readonly-операций) и движемся к распределенной
grid-подобной архитектуре.
> Ничего удивительного. Я в свое время занимался оптимизацией отчетов, > которые уже были написаны на SQL. Но их писали индусы, имеющие самое > отдаленное представление о планах запросов и механике SQL Server, > поэтому нудное и кропотливое переписывание SQL выигрывало тоже от > порядка до двух. Просто благодаря выбору правильного порядка join/group by.
Оно в первой версии около часа работало — минутой оно стало после
тюнинига. Дальше просто уже было непонятно как можно "малой кровью" без
жутких хаков оптимизировать.
> А вот переписывание его с нуля > на том же MS SQL, аккуратная раздача индексов, и прочие методы > традиционной медицины творят просто чудеса.
Традиционная медецина в виде реляционной алгебры и [де]нормализации
схемы — это все понятно. Просто что делать, если задача в терминах
реляционной алгебры вообще не выражается?