Estoy tratando de ejecutar la siguiente instrucción SQL en Oracle, y que lleva mucho tiempo, para ejecutar:optimización de una consulta SELECT que corre lento en Oracle, que rápidamente se ejecuta en SQL Server
SELECT orderID FROM tasks WHERE orderID NOT IN
(SELECT DISTINCT orderID FROM tasks WHERE
engineer1 IS NOT NULL AND engineer2 IS NOT NULL)
Si me quedo sólo el sub-parte que está en la cláusula IN, que se ejecuta muy rápidamente en Oracle, es decir
SELECT DISTINCT orderID FROM tasks WHERE
engineer1 IS NOT NULL AND engineer2 IS NOT NULL
¿por qué toda la declaración de llevar mucho tiempo en Oracle? En SQL Server toda la instrucción se ejecuta rápidamente.
¿Existe una declaración SQL más simple/diferente/mejor que debo utilizar?
algunos detalles más sobre el problema:
- Cada pedido está hecho de muchas tareas
- se asignará Cada pedido (uno o más de sus funciones tendrán engineer1 y ENGINEER2 establecido) o el orden puede estar sin asignar (toda su tarea tiene valores nulos para los campos de ingeniero)
- Estoy tratando de encontrar todos los ID de pedido que no están asignados.
Por si acaso hace alguna diferencia, hay ~ 120k filas en la tabla, y 3 tareas por orden, por lo que ~ 40k pedidos diferentes.
Las respuestas a las respuestas:
- yo preferiría una instrucción SQL que funciona tanto en SQL Server y Oracle.
- Las tareas solo tienen un índice en orderID y taskID.
- Probé la versión NO EXISTE de la declaración, pero se ejecutó durante más de 3 minutos antes de que la cancelara. Tal vez necesita una versión JOIN de la declaración?
- También hay una tabla de "pedidos" con la columna orderID. Pero estaba tratando de simplificar la pregunta al no incluirla en la declaración SQL original.
Supongo que en la declaración SQL original, la subconsulta se ejecuta cada vez para cada fila en la primera parte de la declaración SQL, aunque es estática y solo debe ejecutarse una vez.
Ejecución
ANALYZE TABLE tasks COMPUTE STATISTICS;
hizo que mi instrucción SQL original de ejecutar mucho más rápido.
Aunque todavía tengo curiosidad por saber por qué tengo que hacer esto, y si/cuándo tendría que volver a ejecutarlo?
Las estadísticas dan optimzer información basada en los costes de Oracle que que necesita para determinar la eficiencia de los diferentes planes de ejecución: para ejemplo, el número de rowsin una mesa, la anchura media de filas, más alto y valores más bajos por columna, número de valores distintos por columna, agrupamiento factor de índices, etc.
En una pequeña base de datos puede simplemente configurar un trabajo para recopilar estadísticas todas las noches y dejarlo en paz. De hecho, esto es por defecto debajo de 10g. Para las implementaciones más grandes de , generalmente tiene que sopesar la estabilidad de los planes de ejecución en comparación con la forma en que cambian los datos , lo cual es un equilibrio complicado.
Oracle también tiene una característica llamada "muestreo dinámico" que se utiliza para tablas de ejemplo para determinar estadísticas relevantes en tiempo de ejecución. Es mucho más a menudo utilizado con los datos almacenes donde la sobrecarga del muestreo superado por el aumento de rendimiento potencial para una consulta de larga duración .
Nunca entenderé por qué los programadores a menudo ponen DISTINCT en sus cláusulas IN. ¿7 en (1, 1, 1, 1, 2, 2, 2, 7)? ¿Es 5? La respuesta no cambia si mi lista es (1, 2, 7). Cuando ejecuto esto en Oracle, simplemente ignora lo distinto ... la CBO se da cuenta de que no hay ningún valor. –