MySQL: JOIN y utilizando el índice en una consulta ORDER BY
-
28-09-2019 - |
Pregunta
Tengo un sistema que es similar a los Q & Una característica de stackoverflow. La principal diferencia es el sombrero cada pregunta tiene una fecha y hora de caducidad:
CREATE TABLE questions (
id INT NOT NULL AUTO_INCREMENT,
title CHAR(100) NOT NULL,
details TEXT
PRIMARY KEY (id)
)
CREATE TABLE answers (
id INT NOT NULL AUTO_INCREMENT,
question_id INT NOT NULL
details TEXT
expiration_datetime DATETIME
score INT
PRIMARY KEY (id)
)
Quiero mostrar una cuestión, junto con la parte superior N respuestas que no hayan expirado ordenado por puntuación. Estoy pensando en algo como esto:
SELECT * FROM questions, answers
WHERE questions.id=1 AND questions.id=answers.question_id AND answers.expiration_datetime > NOW()
ORDER BY answers.score DESC LIMIT 10
Algunas preguntas:
1) es la consulta por encima de la forma más eficiente de hacer lo que quiero? ¿Cómo es diferente de usar explícitamente ÚNETE tales como:
SELECT * FROM questions JOIN answers ON questions.id=answers.question_id
WHERE questions.id=1 AND answers.expiration_datetime > NOW()
ORDER BY answers.score DESC LIMIT 10
2) ¿Cómo hacer que mi índice de uso de la consulta? Estoy pensando en la adición de este índice para respuestas TABLA:
INDEX (question_id, expiration_datetime, score)
¿Podría el anterior trabajo de índice para mi consulta? No parece correcto porque expiration_datetime es ascendente, mientras que necesito puntuación a ser descendente. ¿Qué puedo hacer yo aquí?
Solución
La unión con mesas INNER JOIN o en la cláusula FROM da el mismo plan de ejecución. Sin embargo, el primero es mucho más fácil de leer (y eso es lo que sugieren estándar desde 1992).
Sus RDBMS utilizarán un índice siempre que sea posible. Por lo general es una buena idea imprimir el plan de ejecución (EXPLAIN SELECT * FROM -- ...
). Sin embargo, tenga en cuenta que la creación de índice de múltiples columnas puede ser complicado. En su caso, puede utilizar el índice en question_id pero no en expiration_datetime o la puntuación porque no son las primeras columnas del índice. Usted tendría que hacer tres índice diferente.
P.S. SELECT * No se recommanded. Siempre escriba las columnas que necesita (fácil de leer y releer) y sólo menciona las columnas que va a utilizar. No tiene sentido para seleccionar, por ejemplo, initial_date si nunca utiliza esta columna en su guión!