Actualización:
Consulte este artículo en mi blog para obtener una estrategia de indexación eficiente para su consulta utilizando columnas calculadas:
La idea principal es que solo calculamos la length
redondeada y startDate
para sus rangos y luego búsquelos usando condiciones de igualdad (que son buenas para B-Tree
índices)
En MySQL
y en SQL Server 2008
podrías usar SPATIAL
índices (R-Tree
).
Son particularmente buenos para condiciones como "seleccionar todos los registros con un punto dado dentro del rango del registro", que es justo su caso.
Almacenas la start_date
y end_date
como el principio y el final de un LineString
(convirtiéndolos a UNIX
marcas de tiempo de otro valor numérico), indexarlos con un SPATIAL
indexe y busque todos esos LineString
s cuyo cuadro delimitador mínimo (MBR
) contiene el valor de la fecha en cuestión, usando MBRContains
.
Vea esta entrada en mi blog sobre cómo hacer esto en MySQL
:
y una breve descripción general del rendimiento de SQL Server
:
Se puede aplicar la misma solución para buscar una IP
dada contra rangos de red almacenados en la base de datos.
Esta tarea, junto con su consulta, es otro ejemplo de tal condición que se usa con frecuencia.
B-Tree
simple los índices no son buenos si los rangos pueden superponerse.
Si no pueden (y lo sabes), puedes usar la brillante solución propuesta por @AlexKuznetsov
También tenga en cuenta que el rendimiento de esta consulta depende totalmente de su distribución de datos.
Si tiene muchos registros en B
y pocos registros en A
, podría crear un índice en B.dates
y dejar que el TS/CIS
en A
ir.
Esta consulta siempre leerá todas las filas de A
y usará Index Seek
en B.dates
en un bucle anidado.
Si sus datos se distribuyen al revés, i. mi. tienes muchas filas en A
pero pocos en B
, y los rangos son generalmente cortos, entonces podría rediseñar un poco sus tablas:
A
start_date interval_length
, cree un índice compuesto en A (interval_length, start_date)
y usa esta consulta:
SELECT *
FROM (
SELECT DISTINCT interval_length
FROM a
) ai
CROSS JOIN
b
JOIN a
ON a.interval_length = ai.interval_length
AND a.start_date BETWEEN b.date - ai.interval_length AND b.date