tipos resueltos ejercicios ejemplos datos consultas complejas sql static-analysis cyclomatic-complexity

resueltos - select sql ejemplos



MediciĆ³n de la complejidad de las sentencias SQL. (9)

La complejidad de los métodos en la mayoría de los lenguajes de programación se puede medir en la complejidad ciclomática con analizadores de código fuente estáticos. ¿Existe una métrica similar para medir la complejidad de una consulta SQL?

Es lo suficientemente simple para medir el tiempo que tarda una consulta en regresar, pero ¿qué sucede si solo quiero poder cuantificar qué tan complicada es una consulta?

[Editar / Nota] Aunque obtener el plan de ejecución es útil, eso no es necesariamente lo que estoy tratando de identificar en este caso. No estoy buscando qué tan difícil es para el servidor ejecutar la consulta, estoy buscando una métrica que identifique qué tan difícil fue para el desarrollador escribir la consulta y qué tan probable es que contenga un defecto.

[Editar / Nota 2] Es cierto que hay momentos en que medir la complejidad no es útil, pero también hay momentos en que lo es. Para una discusión adicional sobre ese tema, vea esta pregunta .


Bueno, no conozco ninguna herramienta que hiciera tal cosa, pero me parece que lo que haría una consulta más complicada se mediría por: el número de uniones, el número de condiciones, el número de funciones, el número de subconsultas el número de conversiones para diferentes tipos de datos el número de declaraciones de casos el número de bucles o cursores el número de pasos en una transacción

Sin embargo, si bien es cierto que las consultas más complejas pueden parecer las que tienen los defectos más posibles, me parece que es muy probable que las preguntas simples contengan defectos, ya que es más probable que estén escritas por alguien que no entiende. El modelo de datos y, por tanto, pueden parecer que funcionan correctamente, pero en realidad devuelven los datos incorrectos. Así que no estoy seguro de que una métrica así te diga mucho.


Bueno, si está utilizando SQL Server, diría que debería considerar el costo de la consulta en el plan de ejecución (específicamente el costo del subárbol).

Here hay un enlace que repasa algunas de las cosas que debe ver en el plan de ejecución.


Dependiendo de su RDBMS, puede haber herramientas de planificación de consultas que pueden ayudarlo a analizar los pasos que el RDBMS tomará para obtener su consulta.

SQL Server Management Studio Express tiene un plan de ejecución de consulta incorporado. Pervasive PSQL tiene su buscador de planes de consulta. DB2 tiene herramientas similares (se olvidó de cómo se llaman).


En ausencia de herramientas que hagan esto, un enfoque pragmático sería garantizar que las consultas que se analizan tengan un formato coherente y luego contar las líneas de código.

Alternativamente, use el tamaño de las consultas en bytes cuando se guarde en un archivo (teniendo cuidado de que todas las consultas se guarden utilizando la misma codificación de caracteres).

No brillante, pero un proxy razonable para la complejidad en ausencia de cualquier otra cosa, creo.


Las consultas de SQL son declarativas en lugar de de procedimiento: no especifican cómo lograr su objetivo. El motor SQL creará un plan de ataque de procedimiento, y ese podría ser un buen lugar para buscar complejidad. Intente examinar la salida de la declaración EXPLAIN (o EXPLAIN PLAN), será una descripción aproximada de los pasos que el motor utilizará para ejecutar su consulta.


Las medidas comunes de la complejidad del software incluyen la Complejidad ciclomática (una medida de cuán complicado es el flujo de control) y la complejidad de Halstead (una medida de lo complejo que es la aritmética).

El "flujo de control" en una consulta SQL se relaciona mejor con los operadores "y" y "o" en la consulta.

La "complejidad computacional" se relaciona mejor con operadores como SUM o JOINS implícitos.

Una vez que haya decidido cómo categorizar cada unidad de sintaxis de una consulta SQL en cuanto a si se trata de "flujo de control" o "cálculo", puede calcular directamente las medidas de Cyclomatic o Halstead.

Lo que hace el optimizador de SQL a las consultas, creo que es absolutamente irrelevante. El propósito de las medidas de complejidad es caracterizar qué tan difícil es para una persona entender la consulta, no cómo la eficiencia puede evaluarse.

De manera similar, lo que dice el DDL o si las vistas están involucradas o no, no deberían incluirse en tales medidas de complejidad. El supuesto detrás de estas métricas es que la complejidad de la maquinaria dentro de una abstracción usada no es interesante cuando simplemente se invoca, porque presumiblemente esa abstracción hace algo bien entendido por el codificador. Esta es la razón por la que las medidas de Halstead y Cyclomatic no incluyen subrutinas llamadas en su conteo, y creo que puede hacer un buen caso de que las vistas y la información DDL son esas abstracciones "invocadas".

Finalmente, no importa mucho cuán perfectamente correctas o perfectamente estén equivocadas estos números de complejidad, siempre que reflejen algo de verdad acerca de la complejidad y puedan compararse entre sí. De esa manera, puede elegir qué fragmentos de SQL son los más complejos, así clasificarlos todos y centrar su atención de prueba en los más complicados.


No estoy seguro de que la recuperación de los planes de consulta responda a la pregunta: los planes de consulta ocultan una parte de la complejidad sobre el cálculo realizado en los datos antes de que se devuelvan (o se usen en un filtro); los planes de consulta requieren una base de datos significativa para ser relevante. De hecho, la complejidad y la duración de la ejecución son opuestas; algo así como "Bueno, rápido, barato: elige dos".

En última instancia, ¿se trata de las posibilidades de cometer un error o de no entender el código que he escrito?

Algo como:

  • número de tablas veces (1
  • +1 por expresión de combinación (+1 por combinación externa?)
  • +1 por predicado después de WHERE o HAVING
  • +1 por expresión de GROUP BY
  • +1 por UNION o INTERSECT
  • +1 por llamada de función
  • +1 por expresión CASE
  • )


Una buena pregunta El problema es que para una consulta SQL como:

SELECT * FROM foo;

la complejidad puede depender de qué es "foo" y de la implementación de la base de datos. Para una función como:

int f( int n ) { if ( n == 42 ) { return 0; } else { return n; } }

No hay tal dependencia.

Sin embargo, creo que debería ser posible obtener algunas métricas útiles para un SELECT, incluso si no son muy exactas, y me interesará ver qué respuestas obtiene.