Здравствуйте, Sinclair, Вы писали:
S>Заодно это положительно влияет на производительность. Из-за того, что код исполняется ближе к данным.
А что будет с производительностью во время batch-update?
Например, когда обновятся ВСЕ ученики школы. Т.е. все старые будут удалены, а все новые добавлены.
Допустим в школе 2000 учеников. Триггер выполнит 4000 обновлений агрегированной таблицы?
Плюс такая операция заблокирует запись других писателей в эту таблицу.
Выполнить COUNT было бы намного быстрее для этой школы. И блокировки удалось бы избежать.
В общем, ответ зависит от частоты и типа обновлений исходной таблицы. И триггер часто не лучшее решение.
Здравствуйте, Буравчик, Вы писали:
Б>Здравствуйте, Sinclair, Вы писали:
S>>Заодно это положительно влияет на производительность. Из-за того, что код исполняется ближе к данным.
Б>А что будет с производительностью во время batch-update? Б>Например, когда обновятся ВСЕ ученики школы. Т.е. все старые будут удалены, а все новые добавлены.
Б>Допустим в школе 2000 учеников. Триггер выполнит 4000 обновлений агрегированной таблицы? Б>Плюс такая операция заблокирует запись других писателей в эту таблицу. Б>Выполнить COUNT было бы намного быстрее для этой школы. И блокировки удалось бы избежать.
Б>В общем, ответ зависит от частоты и типа обновлений исходной таблицы. И триггер часто не лучшее решение.
Здорово, что дискуссия наконец-то добралась до этих деталей. Именно из-за таких размышлений я упомянул в вопросе балк инсерты. Читая из CSV файлов хоть миллион учеников, подсчитать их легко — и потом за 1 апдейт сделать этот самый +1млн. Триггерами ни разу в жизни не пользовался — интересно какой оверхед они добавят если делать этот 1млн плюсадинов.
Здравствуйте, Sharov, Вы писали:
S>Здравствуйте, IID, Вы писали:
S>>>Прекрасно изложено. Я бы ещё попробовал сделать materialized view между 2 и 3. Особенно если частота чтений << частоты записей. IID>>Тут правильное отношение ? Чтений намного МЕНЬШЕ чем записей ?
S>Да, ибо речь про бд. Что-то можно закэшировать и не лезть лишний раз в бд.
Не понимаю.
Кеширование же будет эффективно если записей МЕНЬШЕ. Или ты записи кешировать собрался ?
Здравствуйте, IID, Вы писали:
S>>Да, ибо речь про бд. Что-то можно закэшировать и не лезть лишний раз в бд. IID>Не понимаю. IID>Кеширование же будет эффективно если записей МЕНЬШЕ. Или ты записи кешировать собрался ?
Так необязательно сразу кэш инвалидироавать, некоторое кол-во запросов можно и старым кэшем обслужить.
Здравствуйте, Буравчик, Вы писали:
Б>А что будет с производительностью во время batch-update?
Это зависит от того, насколько взрослую СУБД вы используете. Б>Например, когда обновятся ВСЕ ученики школы. Т.е. все старые будут удалены, а все новые добавлены. Б>Допустим в школе 2000 учеников. Триггер выполнит 4000 обновлений агрегированной таблицы?
Во взрослых СУБД триггер активируется 1 раз на стейтмент. То есть если у вас выполняется один delete, а потом один батч insert, то триггер сработает 2 раза.
И параметрами триггера будут таблицы inserted и deleted, над которыми можно выполнять агрегатные операции. Итого, будет выполнено 2 update стейтмента для агрегированной таблицы.
Б>Плюс такая операция заблокирует запись других писателей в эту таблицу.
Именно поэтому я сделал оговорку про соотношение объёмов чтений и записей. Если у вас запись относительно редка (а для школ это так и есть), то триггеры и материализованные представления заруливают агрегацию в минуса.
Б>Выполнить COUNT было бы намного быстрее для этой школы. И блокировки удалось бы избежать.
Быстрее, чем что? один count будет быстрее, чем один update from select count(). А вот тысяча count уже окажутся сильно медленнее, чем один update плюс тысяча select from preaggregatedCount where id = @ Б>В общем, ответ зависит от частоты и типа обновлений исходной таблицы. И триггер часто не лучшее решение.
Триггер — лучшее решение по сравнению с application-side триггером, когда мы уже решили использовать предагрегированные таблицы, но строим их руками в коде приложения, а не внутри RDBMS.
Кроме всяких интересных случаев с порядком блокировок: обычно способов управлять порядком срабатывания триггера нет; это может вызывать всякие false locking conflicts вплоть до дедлоков. Ну, и редкая СУБД сейчас понимает коммутативность инкрементальных апдейтов. Как я понимаю, как раз материализованные представления являются хорошим ответом на эту проблему: мало того, что не нужно самостоятельно изобретать код триггера, рискуя накосячить, так ещё и СУБД может догадаться, что две транзакции, одна из которых удаляет учеников, а другая добавляет, не конфликтуют ни по какому ресурсу. Ну, потому что не важно, в каком порядке выполнять update view set count = count + 2 и update view set count = count — 3
Но, положа руку на сердце, сам я это не проверял.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sharov, Вы писали:
S>Здравствуйте, Vladek, Вы писали:
R>>>Триггером или кодом приложения? V>>В коде. Чтобы потом иметь возможность обновить эти данные в любой удобный момент.
S>А почему не триггером и потом просто спросить цифирь у базы? А так получается, что выполняем работу за базу.
Триггер — часть СУБД, а код — часть программы, ты им владеешь и можешь его использовать как угодно когда угодно (посчитать и сохранить в бд, посчитать и показать в отчете, посчитать и сравнить с бд).
Чтобы использовать триггер, нужен ритуал общения с СУБД — ты не владеешь триггером, это часть СУБД, поэтому надо совершать какие-то посторонние действия, чтобы триггер срабатывал. Придётся доверять ответу СУБД, потому что его будет не с чем сравнивать — знание как получить ответ было пожертвовано СУБД, в программе его нет. Придётся уделять время обслуживанию СУБД, погружаться в детали её работы — проблемы с СУБД будут означать проблемы с программой.
СУБД вполне может дублировать функциональность твоей программы — это только увеличит надёжность. Но не замещать — это потеря функциональности и полезности твоей программы.
Здравствуйте, Vladek, Вы писали:
V>Триггер — часть СУБД, а код — часть программы, ты им владеешь и можешь его использовать как угодно когда угодно (посчитать и сохранить в бд, посчитать и показать в отчете, посчитать и сравнить с бд).
Зачем самому делать то, что хорошо делает бд? Тем более если еще надо будет сравнивать с бд для чего-то
V>Чтобы использовать триггер, нужен ритуал общения с СУБД — ты не владеешь триггером, это часть СУБД, поэтому надо совершать какие-то посторонние действия, чтобы триггер срабатывал.
Ну да, СУБД вообще хранит все пользовательские данные, это вообще центральное и ключевое место всего сервиса. Почему бы
там не хранить еще одну цифирь, которую СУБД может лучше и точнее подсчитать?
V>Придётся доверять ответу СУБД, потому что его будет не с чем сравнивать — знание как получить ответ было пожертвовано СУБД, в программе его нет. Придётся уделять время обслуживанию СУБД, погружаться в детали её работы — проблемы с СУБД будут означать проблемы с программой.
Тут отчасти согласен, надо изучать инструмент. Другой вопрос зачем тогда вообще связываться с СУБД? Раз уж связались, в чем
проблема разобраться с триггером?
V>СУБД вполне может дублировать функциональность твоей программы — это только увеличит надёжность. Но не замещать — это потеря функциональности и полезности твоей программы.
Я по-прежнему не понимаю зачем моя программа должна брать на себя задачи СУБД, если вторая явно с этим лучше справится, а
я потрачу время и напложу багов ? Если уж связались с СУБД, то надо использовать возможности инструмента по-максимуму, а не
переписывать с нуля отлаженный функционал СУБД у себя в программе.
Здравствуйте, Sharov, Вы писали:
S>Здравствуйте, Vladek, Вы писали:
S>Я по-прежнему не понимаю зачем моя программа должна брать на себя задачи СУБД, если вторая явно с этим лучше справится, а S>я потрачу время и напложу багов ? Если уж связались с СУБД, то надо использовать возможности инструмента по-максимуму, а не S>переписывать с нуля отлаженный функционал СУБД у себя в программе.
Тогда получается приложение СУБД, а не программа. Это уже философский вопрос. Вообще вера в то, что внутри СУБД уже есть программа заказчика, реализованная и отлаженная, надо её только оттуда извлечь, приводит к нулевой интеллектуальной ценности написанного кода — это будет простой интеграционный код тасования байтов от устройств ввода в базу данных и обратно. Код, который был написан уже тысячу раз, иногда авторы даже тащат целые куски из предыдущих проектов в новый проект.
Код должен моделировать бизнес-процессы и автоматизировать необходимые части, то есть отражать суть того, чем занят бизнес — если считать количество школ и студентов важно, это должно быть отражено в коде. Если правила подсчёта изменятся, код тоже изменится.
Если код примитивен, то у бизнеса вся автоматизация будет сводиться к накоплению данных в базе данных. Это значит, при развитии бизнеса и смене обстоятельств (это может быть что угодно, от смены облачного провайдера из-за дороговизны, до необходимости поддерживать новые платформы), софт, скорее всего, устареет и не будет адаптирован — бизнес сможет использовать только старую базу данных, а код придётся писать заново.
S>>Я по-прежнему не понимаю зачем моя программа должна брать на себя задачи СУБД, если вторая явно с этим лучше справится, а S>>я потрачу время и напложу багов ? Если уж связались с СУБД, то надо использовать возможности инструмента по-максимуму, а не S>>переписывать с нуля отлаженный функционал СУБД у себя в программе.
V>Тогда получается приложение СУБД, а не программа. Это уже философский вопрос.Вообще вера в то, что внутри СУБД уже есть программа заказчика, реализованная и отлаженная, надо её только оттуда извлечь, приводит к нулевой интеллектуальной ценности написанного кода — это будет простой интеграционный код тасования байтов от устройств ввода в базу данных и обратно. Код, который был написан уже тысячу раз, иногда авторы даже тащат целые куски из предыдущих проектов в новый проект.
Я думаю, что для большинства бэка и всяческих 3-х звенок это действительно так. База первична, железо не под BL
докупают, а под базу. И BL во многом пляшет от базы. Я сейчас рассматриваю типовые сценарии, коих большинство, особенно
на дотнет стеке.
V>Код должен моделировать бизнес-процессы и автоматизировать необходимые части, то есть отражать суть того, чем занят бизнес — если считать количество школ и студентов важно, это должно быть отражено в коде. Если правила подсчёта изменятся, код тоже изменится.
Согласен, но если этот функционал пересекается с бд, почему бы не использовать то, что уже сделано и многократно
отлажено? Ну если конкретно речь идет о ф-ии count(), зачем ее самому воспроизводить, наверняка есть
не менее важные задачи (ф-ии), которые с бд не пересекаются?
V>Если код примитивен, то у бизнеса вся автоматизация будет сводиться к накоплению данных в базе данных. Это значит, при развитии бизнеса и смене обстоятельств (это может быть что угодно, от смены облачного провайдера из-за дороговизны, до необходимости поддерживать новые платформы), софт, скорее всего, устареет и не будет адаптирован — бизнес сможет использовать только старую базу данных, а код придётся писать заново.
Полностью согласен, хотя если код на nodejs или ruby, то особых проблем с новыми платформами не будет,
а вот переезд в облака или смена облачного провайдера инвестиций в любой код потребует. Но это такие, глобальные вещи.
Но вообще да, всем нужны данные и потом из этих данных как-то извлекать прибыль. Поэтому по началу бд сильно
первична, поэтому желательно все делать "поближе" к бд.
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, Буравчик, Вы писали:
Б>>В общем, ответ зависит от частоты и типа обновлений исходной таблицы. И триггер часто не лучшее решение. S>Триггер — лучшее решение по сравнению с application-side триггером, когда мы уже решили использовать предагрегированные таблицы, но строим их руками в коде приложения, а не внутри RDBMS.
У меня по факту код аппликейшна обновляет счётчики в БД. Когда кто-то редактирует руками, происходит update ... count = count + 1 (ну или -1 при удалении), а при балк инсертах то же самое, только сразу count=count+100500.
Переписал на триггерах из интереса. Триггер на insert делает +1, и на delete делает -1. Здорово выкинулось много кода из аппликейшна, но балк инсерты стали в 1.5 (полтора) раза медленнее. Под балк инсертами понимается insert from select, аппликейшн в тормозах никак не участвует.
Здравствуйте, rosencrantz, Вы писали: R>Переписал на триггерах из интереса. Триггер на insert делает +1, и на delete делает -1. Здорово выкинулось много кода из аппликейшна, но балк инсерты стали в 1.5 (полтора) раза медленнее. Под балк инсертами понимается insert from select, аппликейшн в тормозах никак не участвует.
Что за СУБД?
В MS SQL триггер будет делать count=count+100500.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, rosencrantz, Вы писали: R>>Переписал на триггерах из интереса. Триггер на insert делает +1, и на delete делает -1. Здорово выкинулось много кода из аппликейшна, но балк инсерты стали в 1.5 (полтора) раза медленнее. Под балк инсертами понимается insert from select, аппликейшн в тормозах никак не участвует. S>Что за СУБД? S>В MS SQL триггер будет делать count=count+100500.
Здравствуйте, rosencrantz, Вы писали: S>>Что за СУБД? S>>В MS SQL триггер будет делать count=count+100500. R>Mysql 8.
Да, для вашей СУБД реализация триггеров на стороне приложения — меньшее зло.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.