what standard significado meaning historia sql history

sql - standard - ¿De dónde viene la práctica "existe(seleccione 1 de...)"?



sql standard (4)

La gran mayoría de las personas apoyan mi propia opinión de que no hay diferencia entre las siguientes afirmaciones:

SELECT * FROM tableA WHERE EXISTS (SELECT * FROM tableB WHERE tableA.x = tableB.y) SELECT * FROM tableA WHERE EXISTS (SELECT y FROM tableB WHERE tableA.x = tableB.y) SELECT * FROM tableA WHERE EXISTS (SELECT 1 FROM tableB WHERE tableA.x = tableB.y) SELECT * FROM tableA WHERE EXISTS (SELECT NULL FROM tableB WHERE tableA.x = tableB.y)

Sin embargo, hoy me encontré cara a cara con la afirmación opuesta cuando en nuestra reunión interna de desarrolladores se recomendó que select 1 es el camino a seguir y select * selecciona todos los datos (innecesarios), lo que perjudica el rendimiento.

Me parece recordar que había una versión antigua de Oracle o algo donde esto era cierto, pero no puedo encontrar referencias a eso. Entonces, tengo curiosidad, ¿cómo nació esta práctica? ¿De dónde se originó este mito?

Agregado: como algunas personas insisten en tener evidencia de que esto es una falsa creencia, aquí: una consulta de Google que muestra a muchas personas que lo dicen así. Si eres demasiado perezoso, revisa este enlace directo donde una persona incluso compara los planes de ejecución para encontrar que son equivalentes.


Como demo, prueba estos

SELECT * FROM tableA WHERE EXISTS (SELECT 1/0 FROM tableB WHERE tableA.x = tableB.y) SELECT * FROM tableA WHERE EXISTS (SELECT CAST(''bollocks'' as int) FROM tableB WHERE tableA.x = tableB.y)

Ahora lea el estándar ANSI. ANSI-92, página 191, caso 3a

If the <select list> "*" is simply contained in a <subquery> that is immediately contained in an <exists predicate>, then the <select list> is equivalent to a <value expression> that is an arbitrary <literal>.

Finalmente, el comportamiento en la mayoría de RDBMS debe ignorar THE * en la cláusula EXISTS. Según esta pregunta de ayer ( Sql Server 2005: insértelo si no existe ) esto no funciona en SQL Server 2000, pero sé que sí lo hace en SQL Server 2005+


Esta pregunta tiene una respuesta que dice que fue alguna versión de MS Access que en realidad no ignoró el campo de la cláusula SELECT . He hecho algo de desarrollo de Access, y he oído que SELECT 1 es la mejor práctica, por lo que me parece que es la fuente del "mito".

Rendimiento de las variantes de uso de SQL EXISTS


La parte principal de su pregunta es: "¿De dónde viene este mito?"

Entonces, para responder a eso, supongo que uno de los primeros consejos de rendimiento que la gente aprende con SQL es que select * es ineficiente en la mayoría de las situaciones. El hecho de que no sea ineficiente en esta situación específica es, por lo tanto, algo intuitivo. Así que no es sorprendente que la gente sea escéptica al respecto. Pero algunas investigaciones o experimentos simples deberían ser suficientes para desterrar la mayoría de los mitos. Aunque la historia humana muestra un poco que los mitos son bastante difíciles de eliminar.


Para SQL Server, Conor Cunningham del equipo de Query Optimiser explica por qué normalmente utiliza SELECT 1

El QP tomará y expandirá todos los * * al principio de la tubería y los vinculará a los objetos (en este caso, la lista de columnas). Luego eliminará las columnas innecesarias debido a la naturaleza de la consulta.

Así que para una subconsulta EXISTS simple como esta:

SELECCIONE col1 DE MyTable WHERE EXISTS (SELECT * FROM Table2 WHERE MyTable.col1 = Table2.col2) El * se expandirá a una lista de columnas potencialmente grande y luego se determinará que la semántica de EXISTS no requiere ninguna de esas columnas , así que básicamente todos ellos pueden ser eliminados.

"SELECT 1" evitará tener que examinar los metadatos que no sean necesarios para esa tabla durante la compilación de la consulta.

Sin embargo, en el tiempo de ejecución, las dos formas de la consulta serán idénticas y tendrán tiempos de ejecución idénticos.

Edit: Sin embargo, he visto esto con cierto detalle desde que publiqué esta respuesta y llegué a la conclusión de que SELECT 1 no evita la expansión de esta columna. Todos los detalles aquí .