2011-09-25 18 views
5

Tengo una tabla de Idno Geo de InnoDB MySQL que tiene ~ 1 millón de filas. La estructura de la tabla es la siguiente:Cómo optimizar aún más esta tabla de MySQL para una única consulta

CREATE TABLE `geoid` (
    `start_ip` int(11) NOT NULL, 
    `end_ip` int(11) NOT NULL, 
    `city` varchar(64) NOT NULL, 
    `region` char(2) NOT NULL, 
    PRIMARY KEY (`start_ip`,`end_ip`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1; 

sólo habrá una consulta de tipo iba en contra de esta tabla:

SELECT city, region FROM geoid WHERE 1259650516 BETWEEN start_ip AND end_ip 

Esta consulta tarda aproximadamente 0,4228 ~ s, lo que no es super lento, pero no increíblemente rápido éter.

Mi pregunta es: ¿Cómo puedo optimizar aún más mi tabla para esta única consulta?

me han tratado las siguientes cosas:

  1. cambiar el motor de almacenamiento MyISAM a, esto hizo que la consulta a tardar alrededor de 1,9 seg.
  2. Utilice la instrucción WHERE 'WHERE geoid.start_ip < = 1259650516 Y 1259650516 < = geoid.end_ip'. Pero eso toma aproximadamente .5 segundos para ejecutar en lugar de .4 ish.

He eliminado todas las filas inútiles de la tabla para hacerla más pequeña. Necesito las 1 millón de filas.

actualizar/SOLUCIÓN

Gracias al artículo siguiente, esto es lo que hice para solucionar este problema. (Sólo para completar esta respuesta para cualquier otra persona interesada)

que añade una nueva columna a la tabla anterior:

ALTER TABLE `geoid` ADD `geoip` LINESTRING NOT NULL 

luego llené la nueva columna con los datos geográficos de start_ip y end_ip

GeomFromText(CONCAT('LINESTRING(', start_ip, ' -1, ', end_ip, ' 1)')) 

entonces creó el índice espacial en la nueva columna

CREATE SPATIAL INDEX geoip_index ON geoid(geoip); 

a partir de ahí, todo lo que tiene que hacer es cambiar su consulta a:

SELECT city, region FROM geoid WHERE MBRContains(geoip, GeomFromText(CONCAT('POINT(', 1259650516, ' 0)'))); 

Y SU HECHO. ¡Esto redujo la consulta de .42 a .0003 segundos !!!!!!!

Me encanta este ÍNDICE. Gracias. Espero eso ayude.

+0

¿Creó un índice 'SPATIAL' en una tabla' InnoDB'? – Quassnoi

+0

Primero lo convertí en MyISAM. – RonSper

Respuesta

3

Intente agregar un índice en end_ip. Esto debería hacer que la consulta sea dos veces más rápida en algunos casos.

Para un rendimiento mucho mejor, debe utilizar un índice SPATIAL, como se explica en this article.

+1

¿Te gusta, además de la primaria? Me gusta: PRIMARY KEY ('start_ip',' end_ip'), KEY 'start_ip' (' start_ip'), KEY 'end_ip' (' end_ip'). Eso no cambió nada. – RonSper

+0

@Ron Sper: Bueno, no acelerará la consulta en todos los casos, y solo da una velocidad relativamente pequeña en otros casos. Si desea un rendimiento mucho mejor, es posible que desee considerar un índice SPATIAL. Vea este artículo: http://explainextended.com/2009/09/29/adjacency-list-vs-nested-sets-mysql/. Pero no es para principiantes. –

+1

WOW, eso es perfecto. Eso es exactamente lo que quería. Gracias. – RonSper

0

Intente crear un índice en todos los campos incluidos en la consulta. en este caso particular, cree un índice en dos campos (start_ip y end_ip)

Cuestiones relacionadas