Oracle puede usar ambos índices. Simplemente no tiene el derecho dos índices.
Considere: si el plan de consulta usa primero su índice en mail.sent_date
, ¿qué se obtiene al mail
? Obtiene todos los mail.id
s donde mail.sent_date
está dentro del rango que proporcionó en su cláusula where
, ¿sí?
por lo que va a mail_to
con una lista de mail.id
s y la mail.name
que dio en su cláusula where
. En este punto, Oracle decide que es mejor escanear la tabla para buscar coincidencias con mail_to.mail_id
s en lugar de usar el índice en mail_to.name
.
Los índices en varchar son siempre problemáticos, y Oracle realmente prefiere escaneos completos de tablas. Pero si le damos a Oracle un índice que contiene las columnas, realmente quiere que se use, y dependiendo de las filas totales de la tabla y las estadísticas, podemos conseguir que lo use. Este es el índice:
create index mail_to_pid_name on mail_to(mail_id, name) ;
Esto funciona en un índice sólo en name
no es así, ya que Oracle no está buscando sólo por un nombre, pero para un mail_id
y un name
.
Por el contrario, si el analizador basado en el costo determina que es más barato ir a la tabla mail_to
primero, y usa su índice en mail_to.name
, ¿qué se puede obtener? Un grupo de mail_to_.mail_id
s para buscar en mail
.Se necesita encontrar filas con los identificadores de y ciertos sent_dates, por lo que:
create index mail_id_sentdate on mail(sent_date, id) ;
Tenga en cuenta que en este caso me he puesto sent_date
por primera vez en el índice, y id
segundos. (Esto es más una cosa intuitiva.)
Una vez más, el punto de referencia es este: al crear índices, debe considerar no solo las columnas en su cláusula where
, sino también las columnas en sus condiciones de unión.
actualización
jthg: sí, siempre depende de cómo se distribuyen los datos. Y sobre cuántas filas hay en la tabla: si son muchas, Oracle hará un escaneo de tabla y un hash, si es muy poco hará un escaneo de tabla. Puede invertir el orden de cualquiera de los dos índices. Al poner send_date primero en el segundo índice, eliminamos la mayoría de las necesidades de un índice únicamente en sent_date
.
¿Hay alguna razón por la que no se pueda hacer una #TemTable e indexe eso en esas dos columnas? – JNK
@JNK: Veo su tabla templada indexada, y le planteo una vista materializada ... –
@OMG Ponies - +1, usted es el experto que acabo de pasar y repito de vez en cuando :) También ' No estoy muy familiarizado con Oracle, principalmente uso SQL Server 2008. – JNK