Короче я бы согласился с вашим техническим директором. Вероятно, вы достигли некоторой производительности за счет масштабируемости (если эти термины сбивают с толку, я поясню ниже). Две мои самые большие заботы - это ремонтопригодность и отсутствие вариантов горизонтального масштабирования (при условии, что вам это понадобится).
Близость к данным: давайте сделаем шаг назад. Есть несколько веских причин для вставки кода в БД. Я бы сказал, что самым большим из них будет близость к данным - например, если вы ожидаете, что вычисление вернет несколько значений, но это совокупность миллионов записей, отправка миллионов записей (по запросу) поверх сеть, которая будет собираться в другом месте, чрезвычайно расточительна и может легко убить вашу систему. Сказав это, вы можете достичь этой близости данных другими способами, в основном используя кеши или базы данных анализа, где некоторая агрегация выполняется заранее.
Производительность кода в БД:Вторичные эффекты производительности, такие как «кэширование планов выполнения», спорить труднее. Иногда кэшированные планы выполнения могут быть очень негативным явлением, если неправильный план выполнения был кэширован. В зависимости от вашей RDBMS вы можете получить максимальную отдачу от них, но в большинстве случаев вы не получите слишком много от параметризованного SQL (эти планы обычно тоже кэшируются). Я также утверждаю, что большинство скомпилированных или JIT-языков обычно работают лучше, чем их эквиваленты SQL (такие как T-SQL или PL / SQL) для базовых операций и нереляционного программирования (манипулирование строками, циклы и т. Д.), Так что вы бы не стали не потеряйте ничего, если вы использовали что-то вроде Java или C # для вычисления числа. Детальная оптимизация также довольно сложна - на БД вы Вы часто придерживаетесь универсального B-дерева (индекса) в качестве единственной структуры данных. Чтобы быть справедливым, полный анализ, включая такие вещи, как длительные транзакции, эскалация блокировок и т. Д., Может заполнить книги.
Поддержка: SQL - прекрасный язык для того, для чего он был разработан. Я не уверен, что это отлично подходит для логики приложения. Большинство инструментов и методов, которые делают нашу жизнь сносной (TDD, рефакторинг и т. Д.), Трудно применить для программирования баз данных.
Производительность и масштабируемость:Чтобы пояснить эти термины, я имею в виду следующее: производительность - это скорость, с которой вы ожидаете, что один запрос пройдет через вашу систему (и обратно к пользователю), в настоящий момент, предполагая низкую нагрузку. Это часто ограничивается такими вещами, как количество физических уровней, через которые он проходит, насколько хорошо оптимизированы эти уровни и т. Д. Масштабируемость - это то, как изменяется производительность с увеличением количества пользователей / нагрузки. У вас может быть средняя / низкая производительность (скажем, 5 секунд + для запроса), но потрясающая масштабируемость (способная поддерживать миллионы пользователей). В вашем случае вы, вероятно, будете испытывать хорошую производительность, но ваша масштабируемость будет зависеть от того, насколько большой сервер вы можете физически построить. В какой-то момент вы достигнете этого предела и будете вынуждены обратиться к таким вещам, как шардинг, что может оказаться невозможным в зависимости от характера приложения.
Преждевременная оптимизация. В конечном счете, я думаю, что вы допустили ошибку преждевременной оптимизации. Как уже отмечали другие, у вас нет измерений, показывающих, как будут работать другие подходы. Ну, мы не всегда можем создать полномасштабные прототипы, чтобы доказать или опровергнуть теорию ... Но в целом, я всегда буду колебаться, выбирая подход, который меняет удобство обслуживания (вероятно, самое важное качество приложения) на производительность ,
РЕДАКТИРОВАТЬ: на положительной ноте, вертикальное масштабирование может простираться довольно далеко в некоторых случаях. Насколько я знаю, SO довольно долго работал на одном сервере. Я не уверен, насколько это соответствует вашим 10 000 пользователей (я думаю, это будет зависеть от характера того, что они делают в вашей системе), но это дает вам представление о том, что можно сделать (на самом деле, есть далеко более впечатляющие примеры, это просто популярность, которую люди могут легко понять).
РЕДАКТИРОВАТЬ 2: Чтобы уточнить и прокомментировать несколько вещей, поднятых в другом месте:
- Re: Атомная согласованность - согласованность ACID вполне может быть требованием системы. Вышесказанное на самом деле не противоречит этому, и вы должны понимать, что согласованность ACID не требует от вас выполнения всей вашей бизнес-логики внутри БД. Перемещая код, который не обязательно должен быть там, в БД, вы ограничиваете его выполнение в физической среде остальной БД - он конкурирует за те же аппаратные ресурсы, что и фактическая часть управления данными вашей БД. Что касается масштабирования только кода на другие серверы БД (но не фактические данные) - конечно, это возможно , но что именно вы получаете здесь, кроме дополнительных затрат на лицензирование в большинстве случаев? Храните вещи, которые не должны быть в БД, вне БД.
- Re: производительность SQL / C # - так как это кажется интересной темой, давайте добавим немного к обсуждению. Вы, конечно, можете запускать собственный код / Java / C # внутри БД, но, насколько я знаю, это не то, что здесь обсуждалось - мы сравниваем реализацию типичного кода приложения в чем-то вроде T-SQL с чем-то вроде C #. Существует ряд проблем, которые раньше было трудно решить с помощью реляционного кода - например, рассмотрим проблему «максимального числа одновременных входов в систему», когда у вас есть записи, указывающие логин или выход из системы, а также время, и вам нужно выяснить, что максимальное количество пользователей, вошедших в систему за один раз, было. Самое простое возможное решение - это перебирать записи и продолжать увеличивать / уменьшать счетчик, когда вы сталкиваетесь с входами в систему / выходом из системы, и отслеживать максимум этого значения.мая(Я не знаю), лучшее, что вы можете сделать, - это CURSOR (чисто реляционные решения имеют разную степень сложности, и попытка решить ее с помощью цикла while приводит к снижению производительности). В этом случае, да, решение C # на самом деле быстрее, чем то, что вы можете достичь в T-SQL, точка. Это может показаться надуманным, но эта проблема может легко проявиться в финансовых системах, если вы работаете со строками, представляющими относительные изменения, и вам необходимо рассчитать агрегированные оконные агрегаты по ним. Хранимые вызовы процедур также, как правило, обходятся дороже - миллион раз вызывайте тривиальный SP и посмотрите, как это можно сравнить с вызовом функции C #. Я намекнул на несколько других примеров выше - я еще не сталкивался с тем, чтобы кто-либо реализовывал правильную хеш-таблицу в T-SQL (такую, которая на самом деле дает некоторые преимущества), хотя это довольно легко сделать в C #. Опять же, есть вещи, в которых БД крутые, и вещи, в которых они не такие крутые. Точно так же, как я не хотел бы делать JOIN, SUM и GROUP BY в C #, я не хочу писать что-то особенно интенсивное использование CPU в T-SQL.