shopkeeper
Таблица имеет следующие поля:
id (bigint),amount (numeric(19,2)),createddate (timestamp)
Допустим, у меня есть таблица выше. Я хочу получить записи за вчерашний день и сгенерировать отчет, напечатав сумму в центах.
Один из способов сделать это - выполнить вычисления в моем Java-приложении и выполнить простой запрос.
Date previousDate ;// $1 calculate in application
Date todayDate;// $2 calculate in application
select amount where createddate between $1 and $2
а затем перебрать записи и конвертировать сумму в центы в моем Java-приложении и создать отчет
Другой способ подобен выполнению вычислений в самом SQL-запросе:
select cast(amount * 100 as int) as "Cents"
from shopkeeper where createddate between date_trunc('day', now()) - interval '1 day' and date_trunc('day', now())
а затем перебрать записи и сгенерировать отчет
С одной стороны, вся моя обработка выполняется в Java-приложении и запускается простой запрос. В другом случае все преобразования и вычисления выполняются в запросе Sql.
Приведенный выше вариант использования является лишь примером, в реальном сценарии таблица может иметь много столбцов, которые требуют обработки аналогичного вида.
Подскажите, пожалуйста, какой подход лучше с точки зрения производительности и других аспектов и почему?
источник
Ответы:
Это зависит от множества факторов, но самое главное:
Как всегда, если вы делаете принести обратно данные в приложение-сервер, минимизируя столбцы и строки будет вашим преимуществом. Убедиться, что запрос настроен и соответствующим образом проиндексирован, поможет любой сценарий.
Re ваше примечание:
Циклический просмотр записей - почти всегда неправильная вещь в sql - написание операции на основе набора является предпочтительным.
Как правило , я предпочитаю свести к минимуму работу базы данных «сохранить эти данные, извлечь эти данные» - однако всегда есть примеры сценариев, когда элегантный запрос на сервере может сэкономить большую пропускную способность.
Также учтите: если это вычислительно дорого, можно ли его где-нибудь кэшировать?
Если вы хотите точное «что лучше»; закодируйте его в обоих направлениях и сравните его (отметив, что первый вариант любого из них, вероятно, не настроен на 100%). Но примите во внимание типичное использование: если в действительности он вызывается 5 раз (отдельно) одновременно, то смоделируйте это: не сравнивайте только одну «1 из этих против 1 из этих».
источник
Позвольте мне использовать метафору: если вы хотите купить золотое ожерелье в Париже, ювелир мог бы сидеть в Кейптауне или Париже, это вопрос мастерства и вкуса. Но вы никогда не отправите тонны золотой руды из Южной Африки во Францию для этого. Руда перерабатывается на месте добычи (или, по крайней мере, в общей зоне), только золото доставляется. То же самое должно быть верно для приложений и баз данных.
Что касается PostgreSQL , вы можете делать на сервере практически все, что угодно. СУБД выделяется при сложных запросах. Для процедурных потребностей вы можете выбрать один из множества языков сценариев на стороне сервера : tcl, python, perl и многие другие. В основном я использую PL / pgSQL , хотя.
В худшем случае будет многократный переход на сервер для каждой отдельной строки большего набора. (Это будет похоже на перевозку одной тонны руды за раз.)
Второй в очереди , если вы отправляете каскад запросов, каждый из которых зависит от предыдущего, тогда как все это может быть выполнено в одном запросе или процедуре на сервере. (Это похоже на последовательную доставку золота и каждой драгоценности отдельным кораблем.)
Переход от приложения к серверу обходится дорого. Для сервера и клиента. Постарайтесь сократить это, и вы выиграете - следовательно: используйте серверные процедуры и / или сложный SQL, где это необходимо.
Мы только что закончили проект, где упаковали почти все сложные запросы в функции Postgres. Приложение передает параметры и получает необходимые наборы данных. Быстрый, чистый, простой (для разработчика приложений) ввод / вывод сведен к минимуму ... блестящее ожерелье с низким углеродным следом.
источник
В этом случае вы, вероятно, немного лучше выполнять вычисления в SQL, поскольку ядро базы данных, скорее всего, будет иметь более эффективные десятичные арифметические процедуры, чем Java.
В целом, хотя для вычислений на уровне строк нет большой разницы.
Где это имеет значение:
источник
Нет чёрного / белого относительно того, какие части логики доступа к данным должны выполняться в SQL и какие части должны выполняться в вашем приложении. Мне нравится формулировка Марка Гравелла , различающая
Мощь и выразительность SQL сильно недооценены. Начиная с введения оконных функций , множество не строго ориентированных на множество вычислений может быть очень легко и элегантно выполнено в базе данных.
Всегда следует соблюдать три практических правила, независимо от общей архитектуры приложения:
По моему опыту, с приличным администратором баз данных и некоторыми приличными знаниями о вашей достойной базе данных вы не очень скоро столкнетесь с ограничениями ЦП ваших БД.
Некоторое дальнейшее чтение, где объясняются эти вещи:
источник
В общем, делайте что-то в SQL, если есть вероятность, что другим модулям или компонентам в тех же или других проектах потребуется получить эти результаты. атомарная операция, выполняемая на стороне сервера, также лучше, потому что вам просто нужно вызвать сохраненный процесс из любого инструмента управления БД, чтобы получить окончательные значения без дальнейшей обработки.
В некоторых случаях это не относится, но когда это имеет смысл. Кроме того, в целом дБ-бокс имеет лучшее оборудование и производительность.
источник
Если вы пишете поверх ORM или пишете случайные низкопроизводительные приложения, используйте любой шаблон, упрощающий приложение. Если вы пишете высокопроизводительное приложение и внимательно относитесь к масштабу, вы выиграете, перейдя к обработке данных. Я настоятельно рекомендую перенести обработку данных.
Давайте подумаем об этом в два этапа: (1) транзакции OLTP (небольшое количество записей). (2) OLAP (длинные сканы многих записей).
В случае OLTP, если вы хотите быть быстрым (10 000–100 000 транзакций в секунду), вы должны удалить конфликты защелок, блокировок и блокировок из базы данных. Это означает, что вам необходимо исключить длинные задержки в транзакциях: циклические переходы от клиента к БД для переноса обработки на клиент являются одним из таких долгих остановок. Вы не можете иметь долгосрочные транзакции (чтобы сделать чтение / обновление атомарными) и иметь очень высокую пропускную способность.
Re: горизонтальное масштабирование. Современные базы данных масштабируются горизонтально. Эти системы уже реализуют HA и отказоустойчивость. Воспользуйтесь этим и постарайтесь упростить пространство своего приложения.
Давайте посмотрим на OLAP - в этом случае должно быть очевидно, что перетаскивание террабайтов данных обратно в приложение - ужасная идея. Эти системы созданы специально для чрезвычайно эффективной работы со сжатыми, предварительно организованными столбчатыми данными. Современные OLAP-системы также масштабируются по горизонтали и имеют сложные планировщики запросов, которые распределяют работу по горизонтали (внутренне перемещая обработку к данным).
источник
Выполнять ли вычисления в клиентской части или в серверной части очень решено, можем ли мы определить нашу цель в реализации бизнеса. В то же время Java-код может работать лучше, чем SQL-код, и хорошо написано, или это может быть наоборот. Но все же, если вы запутались, вы можете попытаться определить сначала -
Есть много других аспектов, о которых вы можете подумать, прежде чем решить, где разместить код. Одно восприятие совершенно неверно - все лучше всего можно сделать в Java (код приложения) и / или все лучше всего сделать с помощью db (sql code).
источник
С точки зрения производительности: это очень простая арифметическая операция, которая почти наверняка может быть выполнена намного быстрее, чем фактическая выборка данных с дисков, лежащих в основе базы данных. Кроме того, вычисление значений в предложении where может быть очень быстрым в любой среде выполнения. Таким образом, узким местом должен быть дисковый ввод-вывод, а не вычисление значений.
Что касается читабельности, я думаю, что если вы используете ORM, вы должны делать это в своей среде сервера приложений, потому что ORM позволит вам очень легко работать с базовыми данными, используя операции на основе множеств. В любом случае, если вы собираетесь писать сырой SQL, нет ничего плохого в выполнении вычислений, ваш SQL также выглядел бы немного лучше и легче для чтения, если правильно отформатирован.
источник
Важно отметить, что «производительность» не определена.
Для меня важнее всего время разработки.
Напишите запрос SQL. Если он слишком медленный или БД становится узким местом, то пересмотрите. К тому времени вы сможете сравнить два подхода и принять решение на основе реальных данных, относящихся к вашей настройке (аппаратное обеспечение и любой другой стек).
источник
Я не верю, что различия в производительности можно обосновать без конкретных примеров и тестов, но у меня есть другой подход:
Что вы можете поддерживать лучше? Например, вы можете захотеть переключить ваш интерфейс с Java на Flash, или HTML5, или C ++, или что-то еще. Огромное количество программ претерпело такое изменение или даже существует на нескольких языках для начала, потому что они должны работать на нескольких устройствах.
Даже если у вас есть надлежащий средний уровень (из приведенного примера кажется, что это не так), этот уровень может измениться, и JBoss может стать Ruby / Rails.
С другой стороны, маловероятно, что вы замените SQL-бэкенд чем-то, что не является реляционной БД на SQL, и даже если вы это сделаете, вам все равно придется переписывать интерфейс с нуля, так что вопрос спорный.
Моя идея состоит в том, что если вы будете делать вычисления в БД, вам будет гораздо проще написать второй интерфейсный или промежуточный уровень позже, потому что вам не нужно все заново реализовывать. Однако на практике я думаю, «где я могу сделать это с помощью кода, который люди поймут», является наиболее важным фактором.
источник
Чтобы упростить ответ, нужно взглянуть на распределение нагрузки. Вы хотите разместить нагрузку там, где у вас больше всего возможностей (если это имеет смысл). В большинстве систем именно SQL-сервер быстро становится узким местом, поэтому, вероятно, ответ таков: вы не хотите, чтобы SQL выполнял на одну унцию работы больше, чем нужно.
Также в большинстве архитектур именно SQL-сервер (ы) составляют ядро системы и внешних систем, которые добавляются.
Но приведенная выше математика настолько тривиальна, что, если вы не доведите свою систему до предела, лучшее место для нее - это то, где вы хотите ее поставить. Если бы математика не была тривиальной, такой как вычисление sin / cos / tan, скажем, для расчета расстояния, тогда усилия могли бы стать нетривиальными и потребовать тщательного планирования и тестирования.
источник
Другие ответы на этот вопрос интересны. Удивительно, но никто не ответил на ваш вопрос. Вы задаетесь вопросом:
Дополнительная информация: по первому вопросу вы хотите убедиться, что агрегирование дробей работает без ошибок округления. Я думаю, что число 19,2 является разумным для денег, а во втором случае целые числа в порядке. Использование поплавка для денег по этой причине неправильно.
Во втором вопросе мне нравится иметь полный контроль над программистом, какая дата считается «сейчас». При использовании таких функций, как now (), может быть сложно написать автоматические модульные тесты. Кроме того, если у вас более длинный сценарий транзакции, может быть полезно установить переменную, равную now (), и использовать эту переменную так, чтобы вся логика использовала одно и то же значение.
источник
Позвольте мне привести реальный пример для решения этого вопроса.
Мне нужно было рассчитать взвешенную скользящую среднюю на моих данных OHLC, у меня есть около 134000 свечей с символом для каждой, чтобы сделать это
Какой лучше?
Требования
Чтобы поддержать вас, это версия Python для взвешенного скользящего среднего.
WMA сделано через код
WMA через SQL
Хотите верьте, хотите нет, но запрос выполняется быстрее, чем версия Pure Python для взвешенного перемещения! Я пошагово написал этот запрос, так что держись, и у тебя все получится
скорость
0,42141127300055814 секунд Python
0,23801879299935536 секунд SQL
У меня есть 134000 фальшивых записей OHLC в моей базе данных, разделенных на 1000 акций, так что это пример того, где SQL может превзойти ваш сервер приложений
источник