MySQL:JOIN&在ORDER BY查询中使用索引

时间:2010-11-02 17:57:25

标签: mysql join indexing sql-order-by database-optimization

我的系统类似于stackoverflow的Q& A功能。主要区别在于每个问题都有一个到期日期时间:

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)
) 

我想显示一个问题以及按分数排序的前N个非过期答案。我在想这样的事情:

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

几个问题:

1)上面的查询是最有效的方式来做我想要的吗?它与明确使用JOIN有何不同,例如:

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)如何使我的查询使用索引?我正在考虑将这个索引添加到TABLE答案中:

INDEX (question_id, expiration_datetime, score)

以上索引是否适用于我的查询?它似乎不对,因为expiration_datetime在升序时我需要得分降序。我能在这做什么?

1 个答案:

答案 0 :(得分:0)

使用INNER JOIN或FROM子句连接表会提供相同的执行计划。然而,前者更容易阅读(这是自1992年以来的标准建议)。

只要有可能,您的RDBMS就会使用索引。打印执行计划(EXPLAIN SELECT * FROM -- ...)通常是个好主意。但是,请注意,创建多列索引可能会非常棘手。在您的情况下,您可以在question_id上使用index,但在expiration_datetime或score上使用 not ,因为它们不是索引的第一列。你必须制作三个不同的索引。

P.S。不推荐SELECT *。始终键入所需的列(易于阅读和重新阅读),并仅提及您将使用的列。如果您从未在脚本中使用此列,则无需选择例如initial_date!