【问题标题】:MySQL: JOIN & using index in an ORDER BY queryMySQL:在 ORDER BY 查询中加入并使用索引
【发布时间】:2010-11-02 17:57:24
【问题描述】:

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

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)

上述索引是否适用于我的查询?这似乎不正确,因为 expire_datetime 正在上升,而我需要 score 下降。我可以在这里做什么?

【问题讨论】:

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


    【解决方案1】:

    使用 INNER JOIN 或在 FROM 子句中连接表给出了相同的执行计划。但是,前者更容易阅读(这就是自 1992 年以来标准所建议的内容)。

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

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

    【讨论】:

    • 您确定不使用 expire_datetime 吗? MySQL 可以使用多列索引,并且 (question_id, expiration_datetime) 形成索引的最左侧部分。所以我不明白为什么不使用它。
    猜你喜欢
    • 1970-01-01
    • 2017-12-16
    • 2013-02-11
    • 1970-01-01
    • 1970-01-01
    • 2011-09-29
    • 2012-03-27
    • 2021-09-01
    • 1970-01-01
    相关资源
    最近更新 更多