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.
Вышеприведенный пример использования - всего лишь пример, в реальном сценарии таблица может иметь много столбцов, которые требуют обработки подобного рода.
Не могли бы вы рассказать мне, какой подход лучше с точки зрения производительности и других аспектов и почему?
Это зависит от множества факторов - но наиболее важно:
Как всегда, если вы вернете данные на сервер приложений, минимизация столбцов и строк будет в ваших интересах. Убедитесь, что запрос настроен и соответствующим образом проиндексирован, поможет любой сценарий.
Повторите свое примечание:
а затем прокрутите записи
Циклирование по записям - это почти всегда неправильная работа в sql - предпочтительнее писать операцию на основе набора.
Как правило, я предпочитаю, чтобы задание базы данных было минимальным: "Храните эти данные, извлекайте эти данные", однако всегда есть примеры сценариев, в которых элегантный запрос на сервере может сэкономить большую пропускную способность.
Также подумайте: если это вычислительно дорого, можно ли его кэшировать где-то?
Если вам нужен точный "лучше"; код в обоих направлениях и сравнить его (отметив, что первый вариант либо, скорее всего, не на 100% настроен). Но фактор типичного использования для этого: если на самом деле его называют 5 раз (отдельно) сразу, то имитируют это: не сравнивайте ни одного "1 из этих vs 1 из них".
Позвольте мне использовать метафору: если вы хотите купить золотое ожерелье в Париже, ювелир может сидеть в Кейптауне или Париже, это вопрос мастерства и вкуса. Но вы никогда не отправляли тонны золотой руды из Южной Африки во Францию за это. Руда обрабатывается на участке добычи (или, по крайней мере, в общей зоне), только золото отгружается. То же самое должно быть верно для приложений и баз данных.
Что касается PostgreSQL, вы можете сделать почти что угодно на сервере, достаточно эффективно. СУБД превосходит сложные запросы. Для процедурных потребностей вы можете выбрать из серверных script языков: tcl, python, perl и многие другие. В основном я использую PL/pgSQL.
В худшем случае сценарий должен был бы постоянно переходить на сервер для каждой отдельной строки большего набора. (Это будет похоже на отгрузку одной тонны руды за раз.)
Второй в строке, если вы отправляете каскад запросов, каждый из которых зависит от предыдущего, а все это можно сделать в одном запросе или процедуре на сервере. (Это подобно доставке золота и каждой из драгоценностей с отдельным кораблем последовательно).
Переход между приложением и сервером стоит дорого. Для сервера и клиента. Попытайтесь сократить это, и вы выиграете - ergo: при необходимости используйте процедуры на стороне сервера и/или сложный SQL.
Мы только что закончили проект, где мы собрали почти все сложные запросы в хранимые процедуры. Приложение передает параметры и получает нужные ему данные. Быстрая, чистая, простая (для разработчика приложений), ввод-вывод сводится к минимуму... блестящее ожерелье с низким содержанием углерода.
В этом случае вы, вероятно, немного лучше выполняете вычисления в SQL, поскольку механизм базы данных, вероятно, будет иметь более эффективные десятичные арифметические процедуры, чем Java.
В общем, хотя для расчетов на уровне строк нет большой разницы.
Где это имеет значение:
Нет черных/белых относительно того, какие части логики доступа к данным должны выполняться в SQL и какие части должны выполняться в вашем приложении. Мне нравится формулировка Марка Гравелла, различая
Сила и выразительность SQL сильно недооцениваются. Начиная с введения функций многие нестрого ориентированные вычисления могут быть выполнены очень легко и элегантно в базе данных.
Следует соблюдать три правила большого пальца, независимо от общей архитектуры приложения:
По моему опыту, с достойным администратором баз данных и некоторыми достойными знаниями о вашей достойной базе данных, вы не скоро столкнетесь с ограничениями на ваши базы данных.
Дальнейшее чтение, где объясняются эти вещи:
В общем, делайте что-нибудь в SQL, если есть вероятность, что и другие модули или компоненты в тех же или других проектах должны будут получить эти результаты. атомарная операция, сделанная на стороне сервера, также лучше, потому что вам просто нужно вызвать хранимый процесс из любого инструмента управления db, чтобы получить окончательные значения без дальнейшей обработки.
В некоторых случаях это не применяется, но когда это происходит, это имеет смысл. Кроме того, в общем случае коробка db имеет лучшее оборудование и возможности.
Если вы пишете над ORM или записываете случайные низкопроизводительные приложения, используйте любой шаблон, упрощающий приложение. Если вы пишете приложение высокой производительности и тщательно оглядываете масштаб, вы выиграете, перейдя к обработке данных. Я решительно выступаю за перенос обработки данных.
Подумайте об этом в два этапа: (1) OLTP (небольшое количество записей) транзакций. (2) OLAP (длительное сканирование многих записей).
В случае OLTP, если вы хотите быть быстрым (10 тыс. - 100 тыс. транзакций в секунду), вы должны удалить блокировку, блокировку и блокировку блокировки из базы данных. Это означает, что вам необходимо устранить длинные киоски в транзакциях: однократные поездки от клиента к БД для перемещения обработки клиенту - это один такой длинный ларь. Вы не можете долго работать (чтобы сделать чтение/обновление атома) и иметь очень высокую пропускную способность.
Re: горизонтальное масштабирование. Современные базы данных масштабируются горизонтально. Эти системы уже реализуют HA и отказоустойчивость. Используйте это и попробуйте упростить свое прикладное пространство.
Посмотрите на OLAP - в этом случае должно быть очевидно, что перетаскивание, возможно, terrabytes данных обратно в приложение является ужасной идеей. Эти системы созданы специально для эффективной работы с сжатыми, предварительно организованными столбчатыми данными. Современные OLAP-системы также масштабируются по горизонтали и имеют сложные планировщики запросов, которые рассеивают работу по горизонтали (внутренняя обработка данных).
Другие ответы на этот вопрос интересны. Удивительно, но никто не ответил на ваш вопрос. Вам интересно:
Дополнительная информация: Для первого вопроса вы хотите быть уверенным, что объединение фракций работает без ошибок округления. Я думаю, что числовое 19,2 является разумным за деньги, а во втором случае целые числа в порядке. По этой причине использование поплавка за деньги не так.
Для второго вопроса мне нравится иметь полный контроль как программист того, что дата считается "сейчас". Трудно записать автоматический блок тесты при использовании таких функций, как now(). Кроме того, когда у вас больше транзакции script может быть полезно установить переменную, равную now(), и использовать переменную so что вся логика использует то же самое значение.
Чтобы упростить ответ на этот вопрос, нужно посмотреть на балансировку нагрузки. Вы хотите поставить нагрузку там, где у вас больше всего возможностей (если это имеет смысл). В большинстве систем SQL-сервер быстро становится узким местом, поэтому, вероятно, ответ заключается в том, что вы не хотите, чтобы SQL выполнял одну унцию работы больше, чем нужно.
Также в большинстве архитектур это SQL-сервер (ы), которые составляют ядро системы и внешних систем, которые добавляются.
Но приведенная выше математика настолько тривиальна, что, если вы не подталкиваете свою систему к пределу, лучше всего разместить ее там, где вы хотите ее поместить. Если математика не была тривиальной, такой как вычисление sin/cos/tan, например, расчет расстояния, тогда усилие может стать нетривиальным и требует тщательного планирования и тестирования.
Я не считаю, что различия в производительности могут быть обоснованы без конкретных примеров и тестов, но у меня есть еще одно:
Что вы можете поддерживать лучше? Например, вы можете переключить свой интерфейс с Java на Flash или HTML5 или на С++ или что-то еще. Огромное количество программ прошли такое изменение или даже существуют на более чем одном языке для начала, потому что им необходимо работать на нескольких устройствах.
Даже если у вас есть правильный средний уровень (из приведенного примера, похоже, что это не так), этот слой может измениться, а JBoss может стать Ruby/Rails.
С другой стороны, маловероятно, что вы замените SQL-backend тем, что не является реляционной БД с SQL, и даже если вы это сделаете, вам все равно придется переписывать интерфейс с нуля, поэтому точка является спорным.
Моя идея состоит в том, что если вы выполняете вычисления в БД, гораздо легче будет написать второй интерфейс или средний слой позже, потому что вам не нужно повторно выполнять все. На практике, однако, я думаю, что "где я могу это сделать с кодом, который люди поймут" является самым важным фактором.
Реально, "производительность" не определена.
Наиболее важным для меня является время разработки.
Записать запрос SQL. Если он слишком медленный или БД становится узким местом, передумайте. К этому времени вы сможете сравнить два подхода и принять решение на основе реальных данных, относящихся к вашей настройке (аппаратное обеспечение и любой другой стек, на котором вы находитесь).
Формируйте точку зрения производительности: это очень простая арифметическая операция, которая почти наверняка может выполняться намного быстрее, чем фактическое извлечение данных с дисков, которые находятся в основе базы данных. Кроме того, вычисление значений в предложении where может быть очень быстрым в любой среде выполнения. Таким образом, узким местом должен быть диск IO, а не вычисление значений.
В соответствии с читабельностью, я думаю, что если вы используете ORM, вы должны сделать это в своей среде сервера приложений, потому что ORM позволит вам работать с базовыми данными очень легко, используя операции на основе набора. Если вы все равно собираетесь писать raw SQL, нет ничего плохого в том, чтобы делать вычисления там, ваш SQL также выглядел бы немного лучше и легче читать, если отформатировать правильно.
Является ли выполнение вычислений на лицевой стороне или на бэкэнд, очень важно, если мы сможем определить нашу цель в реализации бизнеса. В то время java-код мог бы работать лучше, чем код sql, хорошо написанный или, может быть, наоборот. Но все же, если вы смутитесь, вы можете попытаться определить сначала -
Есть много других аспектов, которые вы можете подумать, прежде чем решать, где разместить код. Одно восприятие совершенно неверно - все может быть сделано лучше всего на Java (код приложения) и/или все лучше всего делать с помощью db (код sql).