2012-02-22 10 views
5

MySQL Server versión: 5.1.41 En Ubuntu 10.04MySQL puntos de vista o cláusula IN vs

me encontré con una diferencia en el comportamiento de MySQL al modificar algunas consultas y quería saber la razón para ello.

Básicamente estoy creando una vista. Cuando consulto la vista, el conjunto de resultados es el mismo Sin embargo, el número de filas leídas es diferente para una cláusula IN que para una cláusula OR. A continuación a continuación es un ejemplo sencillo:

CREATE TABLE country ( 
    id_country int(11) NOT NULL AUTO_INCREMENT, 
    name varchar(50) NOT NULL, 
    PRIMARY KEY (id_country) 
) ENGINE=InnoDB; 

INSERT INTO country (name) VALUES ('A'), ('B'), ('C'), ('D'), ('E'), ('F'), ('G'), ('H'); 

CREATE TABLE status ( 
    id_status int(11) NOT NULL AUTO_INCREMENT, 
    id_country int(11) NOT NULL, 
    status tinyint(4) NOT NULL, 
    PRIMARY KEY (id_status) 
) ENGINE=InnoDB; 
ALTER TABLE status ADD INDEX (id_country); 
ALTER TABLE status ADD FOREIGN KEY (id_country) REFERENCES test.country (id_country) ON DELETE RESTRICT ON UPDATE RESTRICT ; 

INSERT INTO status(id_country, status) VALUES 
(1,0), (2,1), (3,0), (4,1), (5,0),(6,1), (7,0), (8,1); 

CREATE ALGORITHM=MERGE VIEW view_country 
AS 
    SELECT c.*, s.id_status, s.status 
    FROM country c JOIN status s ON c.id_country = s.id_country; 

El 2 explican las declaraciones siguientes muestran diferente número de filas analizado

mysql> EXPLAIN EXTENDED SELECT * FROM view_country WHERE id_country IN (1, 2, 3)\G; 
*************************** 1. row *************************** 
      id: 1 
    select_type: SIMPLE 
     table: c 
     type: range 
possible_keys: PRIMARY 
      key: PRIMARY 
     key_len: 4 
      ref: NULL 
     rows: 3 
    filtered: 100.00 
     Extra: Using where 
*************************** 2. row *************************** 
      id: 1 
    select_type: SIMPLE 
     table: s 
     type: ref 
possible_keys: id_country 
      key: id_country 
     key_len: 4 
      ref: test.c.id_country 
     rows: 1 
    filtered: 100.00 
     Extra: 
2 rows in set, 1 warning (0.00 sec) 

Uso de la cláusula OR

mysql> EXPLAIN EXTENDED SELECT * FROM view_country WHERE id_country = 1 OR id_country = 2 OR id_country = 3\G; 
*************************** 1. row *************************** 
      id: 1 
    select_type: SIMPLE 
     table: s 
     type: ALL 
possible_keys: id_country 
      key: NULL 
     key_len: NULL 
      ref: NULL 
     rows: 8 
    filtered: 37.50 
     Extra: Using where 
*************************** 2. row *************************** 
      id: 1 
    select_type: SIMPLE 
     table: c 
     type: eq_ref 
possible_keys: PRIMARY 
      key: PRIMARY 
     key_len: 4 
      ref: test.s.id_country 
     rows: 1 
    filtered: 100.00 
     Extra: 
2 rows in set, 1 warning (0.00 sec) 

Si nos fijamos en las "filas "en ambas consultas: se suman de manera diferente

La consulta conLa cláusulalee menos filas en comparación con IN, que se suma a las tablas y combinaciones grandes.

¿Alguien me puede ayudar a entender por qué es así?

Gracias por su tiempo.

+0

siempre el mismo pero con diferentes resultados? –

+0

@Marcus - estoy seguro de que no entendí la pregunta - si querías decir que obtuve un resultado coherente cada vez y el número de filas analizadas cada vez también es consistente - entonces la respuesta es sí – naveen

+0

@Marcus Adams - había una copia pegada error de mi parte, lo he corregido. El problema no es sobre diferentes conjuntos de resultados, los conjuntos de resultados son los mismos, pero el número de filas leídas es diferente entre IN y OR. Avíseme si no puede reproducirlo. Estoy en la versión del servidor: 5.1 – naveen

Respuesta

1

Tenga en cuenta que los planes de ejecución tienen mucho que ver con el estado de sus índices y el tamaño de las tablas. MySQL puede ejecutarse de manera diferente incluso para consultas similares, y en ocasiones MySQL puede incluso adivinar incorrectamente.

La vista con el JOIN definitivamente complica las cosas, por lo que su declaración SELECT no es tan simple. No se sorprenda de que MySQL elija un plan de ejecución diferente para IN versus OR.

En el caso de la primera consulta, MySQL ha elegido usar índices para ambas consultas, lo que da como resultado el recuento de filas específico y preciso en EXPLAIN.

Sin embargo, en la segunda consulta, MySQL ha elegido escanear todas las filas en la tabla de estado. Esto tiene sentido ya que hay tan pocas filas y MySQL tiene que visitar la tabla de todos modos porque no hay un índice de cobertura que devuelva todas las filas necesarias. No me sorprendería que la segunda consulta no sea más rápida que la primera. Además, tenga en cuenta que el recuento de filas (para escaneos) en EXPLAIN son estimaciones, así que tenga esto en cuenta al perfilar sus consultas.

La primera consulta tiene que hacer 6 búsquedas, mientras que la segunda consulta solo tiene que hacer 3 búsquedas después de un escaneo de tabla muy corto.

Hay muchos trucos que MySQL hace que a veces se limitan a escenarios muy específicos para tratar de optimizar su consulta, en función de los índices actuales y recuentos de filas. Hay casos documentados donde, for similar queries, MySQL will take two different approaches and end up with the same execution path. Hay otros casos en que dos planes de ejecución completamente diferentes dan como resultado un rendimiento similar, y este es uno de esos casos.

De todos modos, espero que esto explique por qué hay una diferencia, pero siempre y cuando los resultados sean los mismos, y el rendimiento sea similar, no hay nada de qué preocuparse.

En algunos casos, como dije antes, MySQL simplemente no hará la mejor conjetura, y luego puede usar herramientas como indicios de índice y combinaciones naturales. En tu caso, creo que MySQL se está comportando bien.

Para rendimiento de la investigación y planes de ejecución más control hacia fuera los dos sitios siguientes:

+0

gracias por la explicación Marcus - como una buena práctica, creo que necesito pasar por cualquier consulta de combinación compleja y ver cómo mysql selecciona los índices – naveen

0

Si lo entendí correctamente, los resultados que obtiene son los mismos, y que le gustaría saber la diferencia entre la cláusula 'OR' y 'IN' con respecto a la velocidad y la forma en que funcionan.

Si es así, que yo creo que su pregunta es un posible duplicado de éste: IN vs OR in the SQL WHERE Clause

+0

Creo que el OP indicó que los resultados son diferentes usando "IN" en lugar de "O" –

+0

Ah bien, entonces no entendí su pregunta correctamente. Hubiera pensado que los resultados serían los mismos. – Honnes

+0

@ ZackMacomber, de la pregunta: * "el conjunto de resultados es el mismo" *. –