MySQL ORDER BY多个连接的优化

时间:2011-12-29 20:38:50

标签: php mysql optimization join sql-order-by

我需要一些帮助来优化我的数据库的一些查询。我确实理解使用索引来帮助加入和按顺序排序以帮助加快速度,但我想知道是否有一些技术可以避免在使用EXPLAIN命令时使用filesort和使用临时。这是我正在使用的一个例子。

SELECT a.id, DATE_FORMAT(a.submitted_at, '%d-%b-%Y') as submitted_at, a.user_id,
            data1.*, 
            data2.name, data2.type,
            u.first_name, u.last_name               
            FROM applications AS a 
            LEFT JOIN users AS u ON u.id = a.user_id
            LEFT JOIN score_table AS data1 ON data1.applications_id = a.id
            LEFT JOIN sections AS data2 ON data2.id = data1.section_id
            WHERE category_id = [value] && submitted_at IS NOT NULL
            ORDER BY data2.type

同样,索引正在我的查询中正确使用,如上面的那个。如果我取出ORDER BY子句,则使用正确的索引快速执行查询。我知道连接的顺序可能会影响查询的性能。当我在users表上使用ORDER BY进行测试时,由于它是“const”之后的下一个表,因此它将仅使用EXPLAIN上的“Using where,Using Filesort”。如果我放到任何其他表中,我们会进入“使用临时”问题。

我的问题是:优化这类查询的最佳方法是运行得更快,在最佳情况下,避免在EXPLAIN中使用filesort / temporary?我对任何可能性开放:)我或多或少对如何使这样的查询表现更好的理论感兴趣,而不是这个确切的查询,因为我必须执行越来越多这些深层次的ORDER BY查询我正在研究的数据库。

- 编辑 -

以上是上述查询的解释.....

id  select_type     table   type    possible_keys               key         key_len     ref                 rows    Extra
1   SIMPLE          a       ref     category_id,submitted_at    category_id     4           const               49      Using where; Using temporary; Using filesort
1   SIMPLE          u       eq_ref  PRIMARY                     PRIMARY     4           a.user_id           1   
1   SIMPLE          data1   ref     app id                      app id      4           a.id                7   
1   SIMPLE          data2   eq_ref  PRIMARY                     PRIMARY     4           data1.section_id    1   

1 个答案:

答案 0 :(得分:4)

一些事情。

  1. 您确定需要使用'LEFT JOIN'吗?查看查询,看起来您可以使用“INNER JOIN”来减少可能的行数。

  2. 您没有发布您的架构,但我认为users.id,applications.user_id,score_table.applications_id,applications.id,sections.id和score_table.section_id都是整数?如果它们是非英特尔,我强烈建议你转换它们。如果不是主键,请确保它们已编入索引。

  3. 我不会运行任何mysql级数据格式化(即DATE_FORMAT),因为它会在查询期间产生一些开销,而是我会在应用层格式化这样的数据。

  4. ORDER BY强制MySQL创建临时表以便正确排序,因此请确保您绝对需要此功能。如果是这样,请确保将sections.type编入索引。

  5. 我会考虑使用不同的别名命名约定。 data1和data2如此抽象,很难分辨出它们实际指的是什么。我建议你使用表格的缩写结构,例如;应用程序变为app(而不是a),score_table变为分数(而不是data1)等。