En resumen, estaría de acuerdo con su CTO. Probablemente haya ganado algo de rendimiento a expensas de la escalabilidad (si esos términos son confusos, lo aclararé a continuación). Mis dos mayores preocupaciones serían la mantenibilidad y la falta de opciones para escalar horizontalmente (suponiendo que va a necesitar eso).
Proximidad a los datos: demos un paso atrás. Hay algunas buenas razones para insertar código en una base de datos. Yo diría que el más grande sería la proximidad a los datos, por ejemplo, si espera que un cálculo arroje un puñado de valores, pero estas son agregaciones de millones de registros, enviando los millones de registros (a pedido) la red que se agregará en otro lugar es muy derrochadora y podría matar fácilmente su sistema. Dicho esto, puede lograr esta proximidad de datos de otras maneras, esencialmente usando cachés o bases de datos de análisis donde parte de la agregación se realiza por adelantado.
Rendimiento del código en la base de datos:Los efectos de rendimiento secundarios, como el "almacenamiento en caché de los planes de ejecución" son más difíciles de argumentar. A veces, los planes de ejecución en caché pueden ser algo muy negativo, si se almacenó en caché el plan de ejecución incorrecto. Dependiendo de su RDBMS, puede obtener el máximo provecho de estos, pero no obtendrá mucho sobre SQL parametrizado, en la mayoría de los casos (esos planes generalmente también se almacenan en caché). También diría que la mayoría de los lenguajes compilados o JIT generalmente funcionan mejor que sus equivalentes SQL (como T-SQL o PL / SQL) para operaciones básicas y programación no relacional (manipulación de cadenas, bucles, etc.), por lo que no No perderás nada allí, si usaste algo como Java o C # para hacer el cálculo de números. La optimización de grano fino también es bastante difícil: en la base de datos, usted ' a menudo se queda atascado con un árbol B genérico (índice) como su única estructura de datos. Para ser justos, un análisis completo, que incluye cosas como transacciones más largas, escalada de bloqueo, etc., podría llenar libros.
Mantenibilidad: SQL es un lenguaje maravilloso para lo que fue diseñado para hacer. No estoy seguro de que sea una buena opción para la lógica de la aplicación. La mayoría de las herramientas y prácticas que hacen soportable nuestra vida (TDD, refactorización, etc.) son difíciles de aplicar a la programación de bases de datos.
Rendimiento versus escalabilidad:Para aclarar estos términos, quiero decir esto: el rendimiento es lo rápido que esperaría que una sola solicitud pasara por su sistema (y volviera al usuario), por el momento suponiendo una carga baja. Esto a menudo estará limitado por cosas como la cantidad de capas físicas que atraviesa, qué tan bien optimizadas están esas capas, etc. La escalabilidad es cómo cambia el rendimiento con el aumento del número de usuarios / carga. Es posible que tenga un rendimiento medio / bajo (por ejemplo, 5 segundos + para una solicitud), pero una escalabilidad increíble (capaz de admitir millones de usuarios). En su caso, probablemente experimentará un buen rendimiento, pero su escalabilidad estará limitada por el tamaño de un servidor que pueda construir físicamente. En algún momento, alcanzará ese límite y se verá obligado a recurrir a cosas como el fragmentación, que puede no ser factible dependiendo de la naturaleza de la aplicación.
Optimización prematura: en última instancia, creo que ha cometido el error de optimizar prematuramente. Como otros han señalado, realmente no tiene mediciones que muestren cómo funcionarían los otros enfoques. Bueno, no siempre podemos construir prototipos a gran escala para probar o refutar una teoría ... Pero, en general, siempre dudaría en elegir un enfoque que intercambie la capacidad de mantenimiento (probablemente la calidad más importante de una aplicación) por el rendimiento .
EDITAR: en una nota positiva, la escala vertical puede extenderse bastante en algunos casos. Hasta donde yo sé, SO se ejecutó en un solo servidor durante bastante tiempo. No estoy seguro de cómo coincide con sus 10 000 usuarios (supongo que dependerá de la naturaleza de lo que estén haciendo en su sistema), pero le da una idea de lo que se puede hacer (en realidad, hay mucho ejemplos más impresionantes, esto resulta ser uno popular que la gente puede entender fácilmente).
EDITAR 2: Para aclarar y comentar algunas cosas planteadas en otro lugar:
- Re: Consistencia atómica: la consistencia de ACID puede ser un requisito del sistema. Lo anterior realmente no argumenta en contra de eso, y debe darse cuenta de que la consistencia de ACID no requiere que ejecute toda su lógica de negocios dentro de la base de datos. Al mover el código que no necesita estar allí en la base de datos, lo está restringiendo para que se ejecute en el entorno físico del resto de la base de datos: está compitiendo por los mismos recursos de hardware que la porción de administración de datos real de su base de datos. En cuanto a escalar solo el código a otros servidores de base de datos (pero no los datos reales), claro, esto puede ser posible , pero ¿qué está ganando exactamente aquí, aparte de los costos de licencia adicionales en la mayoría de los casos? Mantenga las cosas que no necesitan estar en la base de datos, fuera de la base de datos.
- Re: rendimiento de SQL / C #: dado que esto parece ser un tema de interés, agreguemos un poco a la discusión. Ciertamente, puede ejecutar código nativo / Java / C # dentro de las bases de datos, pero que yo sepa, eso no es lo que se discutió aquí: estamos comparando la implementación de código de aplicación típico en algo como T-SQL versus algo como C #. Hay una serie de problemas que han sido difíciles de resolver con el código relacional en el pasado, por ejemplo, considere el problema de "inicio de sesión máximo concurrente", donde tiene registros que indican un inicio de sesión o cierre de sesión, y el tiempo, y necesita averiguar qué el número máximo de usuarios conectados en cualquier momento fue. La solución más simple posible es iterar a través de los registros y seguir incrementando / decrementando un contador a medida que encuentre inicios de sesión / salidas de sesión, y realizar un seguimiento del máximo de este valor.mayo, No sé), lo mejor que puede hacer es un CURSOR (las soluciones puramente relacionales están en diferentes órdenes de complejidad, e intentar resolverlo usando un bucle while resulta en un peor rendimiento). En este caso, sí, la solución C # es realmente más rápida de lo que puede lograr en T-SQL, punto. Eso puede parecer exagerado, pero este problema puede manifestarse fácilmente en los sistemas financieros, si está trabajando con filas que representan cambios relativos y necesita calcular agregaciones en ventanas en ellas. Las invocaciones de proceso almacenadas también tienden a ser más caras: invoque un SP trivial un millón de veces y vea cómo eso se compara con llamar a una función C #. Insinué algunos otros ejemplos anteriores: aún no he encontrado a nadie que implemente una tabla hash adecuada en T-SQL (una que realmente brinde algunos beneficios), mientras que es bastante fácil de hacer en C #. Una vez más, hay cosas en las que los DB son geniales, y cosas en las que no lo son tanto. Al igual que no quisiera estar haciendo JOINs, SUMs y GROUP BYs en C #, no quiero escribir nada particularmente intensivo de CPU en T-SQL.