que tenía una mesa Bla (float latitud, longitud de flotación, fecha CREATE_TIME, int OWNER_ID, .....)índice compuesto de Oracle para condiciones de consulta de rango
y mi código hace solamente una sola consulta
select *
from Blah
where latitude < l1 and latitude > l2
and longitude < ll1 and longitude > ll2
and create_time < t1 and create_time > t2
and owner_id < o1 and owner_id > o2 ;
(por supuesto, la L1 valores, L2, .... O1, O2 son params dinámicas procedentes de programa)
mi pregunta es qué tipo de índice que debería crear; ¿índice compuesto? en caso de índice compuesto, ¿qué columna debo poner primero? ¿qué tan efectivo es el índice?
Pensé en esto durante mucho tiempo y no pude encontrar documentos detallados sobre cómo funciona el índice de Oracle.
Puedo encontrar documentos que se implementan usando B-tree, en nuestro caso: cada tecla en el B-tree es una 4-tupla: (columna1, columna2, columna3, columna4) donde la relación de ordenamiento de tales tuplas es definido para ser orden léxico
para la consulta anterior, asumiendo que nuestro pedido es (owner_id, create_time, latitude, longitude), supongo que oracle primero necesitaría la búsqueda binaria hasta el punto (o1, t1, l1, ll1), para esta operación , el índice es de hecho útil. pero luego, tenemos que encontrar el punto final de este primer interio: necesitamos encontrar (o1, t1, l1, ll2), esto también se puede hacer mediante búsqueda binaria.
lado, tenemos que encontrar la siguiente sección que satisfaga la condición, por lo que tenemos que find (o1, t1, lx, LL1), donde lx es el siguiente valor más grande que l1, no pudimos encontrar esto mediante la búsqueda binaria también. pero en nuestro caso, es muy probable que, para la misma latitud, no haya más de 1 longitud, , por lo que la búsqueda binaria aquí no es más efectiva que la exploración lineal.
siguiendo este espíritu, parece que debemos poner primero la columna con una cardinalidad de rango de valor pequeño, en este caso, create_time, si nuestros puntos se crean en solo unos pocos días. también, si nunca hacemos condiciones de rango, pero solo equivale a (=) condiciones, entonces no importa qué columna es la primera, ¿verdad?
para hacerlo más claro, aquí es un ejemplo más simple:
digamos que tengo 2 columnas, X, Y y
en el PP, los valores para ambos son [1,2, ... 0,100], por lo que tenemos 100x100 filas
mi consulta es
select * from mytable where X > 34 and X < 78 and Y > 12 and Y < 15;
dicen que nuestro índice está en (X, Y), por lo que la regla de comparación entre los 2 valores son
v1 < v2 <=====> v1.x < v2.x || v1.x == v2.x && v1.y < v2.y
dada la regla de ordenación anterior, podemos ver que los valores en el índice son dispuestos en serie como el (los valores de x, y):
1,1, 1,2 1,3 .... 1,100
2,1 2,2 2,3 ......2,100
.....
100,1 100,2 ....... 100,100
ahora, para buscar los valores de la consulta, el recorrido del árbol B necesita localizar (78-34-1) intervalos, de ahí (78-34-1) * 2 búsqueda (1 para el comienzo uno para las ubicaciones finales), no solo 2 búsquedas.
por lo que si tenemos dimensiones superiores, el intervalo que cuenta aumenta exponencialmente con el número de dimensiones, por lo que la indexación puede no ser útil más ------ esta es mi preocupación
muchas gracias Yang
gracias, pero ahora solo me preocupa el problema del índice B-tree; aunque en la práctica Oracle bien puede usar el índice de mapa de bits, como usted señaló –