2011-02-11 14 views
6

Tengo un gran conjunto de datos (alrededor de 1,9 millones de filas) de puntos 3D que selecciono. La declaración que utiliza con más frecuencia es similar a:aumentando el rendimiento en una consulta SELECT con un gran conjunto de datos de puntos 3D

SELECT * FROM points 
WHERE x > 100 AND x < 200 
AND y > 100 AND y < 200 
AND z > 100 AND z < 200 
AND otherParameter > 10 

tengo índices del sobre x, y, z, así como la otherParameter. También intenté agregar un índice de varias partes a x, y, z, pero eso no ayudó.

¿Algún consejo sobre cómo hacer que esta consulta SELECT sea más rápida?

+1

Tus consultas de rango de uso. Los índices son inútiles. A veces puede hacer que funcione si puede discretizar los valores y usar el operador in. Me gusta: 'donde x en (100, 101, ... 200)' Este es un excelente artículo que explica la diferencia - http://explainextended.com/2009/10/07/in-list-vs-range-condition- mysql/ –

+0

Mira el enlace de nate c, mi "solución" era incorrecta. –

Respuesta

6

B-Tree índices no ayudarán mucho para una consulta de este tipo.

Lo que necesita como un índice R-Tree y la consulta de paralelepípedo de límite mínimo sobre él.

Desafortunadamente, MySQL no admite R-Tree índices de 3d puntos, solo 2d. Sin embargo, es posible crear un índice sobre, digamos, X y Y juntos que será más selectivo que cualquiera de los índices en B-TreeX y Y solo:

ALTER TABLE points ADD xy POINT; 

UPDATE points 
SET  xy = Point(x, y); 

ALTER TABLE points MODIFY xy POINT NOT NULL; 


CREATE SPATIAL INDEX sx_points_xy ON points (xy); 

SELECT * 
FROM points 
WHERE MBRContains(LineString(Point(100, 100), Point(200, 200), xy) 
     AND z BETWEEN 100 and 200 
     AND otherParameter > 10; 

esto sólo es posible si la tabla es MyISAM.

+0

Necesito explorar R-Tree. Es interesante, una de las soluciones potenciales que se me ocurrió fue agregar un campo de octárbol, asignar cada fila a un nodo y luego preprocesar los octrees para seleccionar. Esto ayudó a acelerar las cosas, pero al seleccionar volúmenes más grandes, me encontré con los mismos problemas debido a la gran cantidad de nodos de árbol seleccionados. – clexmond

+0

También estoy interesado en qué bases de datos SI son compatibles con las indizaciones de árbol R 3D? – clexmond

+0

@clexmond: 'PostgreSQL' admite tipos de índice personalizados mediante la interfaz' GiST'.No estoy al tanto de una solución lista para usar para los tipos '3d', sin embargo, con un pequeño esfuerzo puede implementarse fácilmente (si está familiarizado con las partes internas de' R-Tree'). – Quassnoi

-1

no tengo MySQL para probar pero tengo curiosidad qué tan eficiente es su INTERSECT:

 select points.* 
    from points 
    join 
    ( 
    select id from points where x > 100 AND x < 200 
    intersect 
    select id from points where y > 100 AND y < 200 
    intersect 
    select id from points where z > 100 AND z < 200 
    ) as keyset 
    on points.id = keyset.id 

No necesariamente recomendar este - pero es algo para tratar, especialmente si tiene índices separados en x , y y z.

EDITAR: Dado que mySQl no es compatible con INTERSECT, la consulta anterior podría reescribirse utilizando UNIONES de vistas en línea. Cada vista contendría un conjunto de claves y cada vista tendría la ventaja de los índices separados que ha colocado en x, y y z. El rendimiento dependería del numnber de las claves devueltas y del algoritmo de intersección/unión.

Primero probé el enfoque de intersección (en SQLite) para ver si había formas de mejorar el rendimiento en consultas espaciales, salvo el uso de su módulo R-Tree. INTERSECT en realidad fue más lento que usar un único índice no compuesto en uno de los valores espaciales y luego escanear el subconjunto de la tabla base para obtener los otros valores espaciales. Pero los resultados pueden variar según el tamaño de la base de datos. Después de que la tabla ha alcanzado un tamaño gigantesco y el disco I/O se vuelve más importante como factor de rendimiento, puede ser más eficiente interceptar conjuntos de claves discretos, cada uno de los cuales ha sido instanciado a partir de un índice, que hacer una exploración de la tabla base subecuente a un fetch-from-index inicial.

+0

'MySQL' no admite' INTERSECT'. – Quassnoi

+0

Deduciremos un punto de mySQL mientras estamos en ello, por no admitir INTERSECT. – Tim

+0

¿Admite INNER JOINS en vistas en línea? – Tim

Cuestiones relacionadas