Tengo una tabla con millones de registros de rango de IP (inicio_num, final_num respectivamente) que necesito consultar a través de una sola dirección IP para devolver todos los intervalos que se superponen . La consulta es esencialmente:Recuperación eficiente de registros de rango de IP superpuestos a través de un solo punto
SELECT start_num
, end_num
, other_data_col
FROM ip_ranges
WHERE :query_ip BETWEEN start_num and end_num;
la tabla tiene 8 particiones rango en núm_inicial y tiene un índice compuesto local en (núm_inicial, END_NUM). Llámalo UNQ_RANGE_IDX. Las estadísticas se han recopilado en la tabla y el índice.
La consulta realiza un análisis de rango de índice en el índice UNQ_RANGE_IDX como se esperaba y, en algunos casos, funciona muy bien. Los casos en los que funciona bien se encuentran hacia la parte inferior del espacio de direcciones IP (es decir, algo así como 4.4.10.20) y el rendimiento es pobre cuando está en el extremo superior. (es decir, 200.2.2.2) Estoy seguro de que el problema reside en el hecho de que en el extremo inferior, el optimizador puede podar todas las particiones por encima de la que contiene los intervalos aplicables debido a la partición de rango en start_num que proporciona la información necesaria para ciruela pasa. Al consultar en el extremo superior del espectro de IP, no puede podar las particiones inferiores y, por lo tanto, incurre en la E/S de lectura de las particiones de índice adicionales. Esto se puede verificar mediante el número de CR_BUFFER_GETS al rastrear la ejecución.
En realidad, los rangos que satisfacen la consulta no estarán en ninguna partición, excepto aquella en la que está ubicado el query_ip o el inmediatamente debajo o arriba ya que el tamaño del rango no será mayor que una clase A y cada la partición cubre muchas clases A cada una. Puedo hacer que Oracle use esa información al especificarla en la cláusula where, pero ¿hay alguna manera de transmitir este tipo de información a Oracle a través de estadísticas, histogramas o un índice personalizado/de dominio? Parece que habría una solución/enfoque común para este tipo de problema al buscar intervalos de fechas que cubran una fecha específica también.
Estoy buscando soluciones que utilicen Oracle y su funcionalidad para abordar este problema, pero se agradecen otros tipos de soluciones. He pensado en un par de métodos fuera del alcance de Oracle que funcionarían, pero espero una mejor forma de indexación, recopilación de estadísticas o particiones que funcionen bien.
información solicitada:
CREATE TABLE IP_RANGES (
START_NUM NUMBER NOT NULL,
END_NUM NUMBER NOT NULL,
OTHER NUMBER NOT NULL,
CONSTRAINT START_LTE_END CHECK (START_NUM <= END_NUM)
)
PARTITION BY RANGE(START_NUM)
(
PARTITION part1 VALUES LESS THAN(1090519040) TABLESPACE USERS,
PARTITION part2 VALUES LESS THAN(1207959552) TABLESPACE USERS
....<snip>....
PARTITION part8 VALUES LESS THAN(MAXVALUE) TABLESPACE USERS
);
CREATE UNIQUE INDEX IP_RANGES_IDX ON IP_RANGES(START_NUM, END_NUM, OTHER) LOCAL NOLOGGING;
ALTER TABLE IP_RANGES ADD CONSTRAINT PK_IP_RANGE
PRIMARY KEY(START_NUM, END_NUM, OTHER) USING INDEX IP_RANGES_IDX;
No hay nada especial acerca de los valores de corte seleccionados para las particiones de rango. Son simplemente direcciones de clase A donde el número de rangos por partición equivaldría a aproximadamente 1 millón de registros.
¿Cuáles son los tipos de datos de start_num y end_num? –
start_num y end_num son del tipo NUMBER –
¿Cuántas filas hay en la tabla y en cada partición? –