简体   繁体   English

MySQL“正在使用临时”,但此查询中没有匹配的正式原因

[英]Mysql “Using temporary” but no official reason matched in this query

If you look at the official documentation for MySql temporary tables: 如果您查看MySql临时表的官方文档:

http://dev.mysql.com/doc/refman/5.1/en/internal-temporary-tables.html http://dev.mysql.com/doc/refman/5.1/en/internal-temporary-tables.html

The reasons given are: 给出的原因有:

   The server creates temporary tables under conditions such as these:

      Evaluation of UNION statements.

      Evaluation of some views, such those that use the TEMPTABLE algorithm,
      UNION, or aggregation.

      Evaluation of statements that contain an ORDER BY clause and a
      different GROUP BY clause, or for which the ORDER BY or GROUP BY
      contains columns from tables other than the first table in the join queue.

      Evaluation of DISTINCT combined with ORDER BY may require a temporary table.

      For queries that use the SQL_SMALL_RESULT option, MySQL uses an
      in-memory temporary table, unless the query also contains elements
      (described later) that require on-disk storage.

      Evaluation of multiple-table UPDATE statements.

      Evaluation of GROUP_CONCAT() or COUNT(DISTINCT) expressions. 

None of these conditions are met in this query: 此查询均不满足以下条件:

  select ttl.id AS id,
  ttl.name AS name,
  ttl.updated_at AS last_update_on,
  ttl.user_id AS list_creator,
  ttl.retailer_nomination_list AS nomination_list,
  ttl.created_at AS created_on,
  tv.name AS venue_name,
  from haha_title_lists ttl 
    left join haha_title_list_to_users tltu on  ((ttl.id = tltu.title_list_id))
    left join users u on  ((tltu.user_id = u.id)) 
    left join users u2 on  ((tltu.user_id = u2.id)) 
    left join haha_title_list_to_venues tlv on  ((ttl.id = tlv.title_list)) 
    left join haha_venue_properties tvp on  ((tlv.venue_id = tvp.id)) 
    left join haha_venues tv on  ((tvp.venue_id = tv.id))
    join haha_title_list_to_books tlb on  ((ttl.id = tlb.title_list_id))
    join wawa_title ot on  ((tlb.title_id = ot.title_id))
    join wawa_title_to_author ota on  ((ot.title_id = ota.title_id))
    join wawa_author oa on  ((ota.author_id = oa.author_id))
    group by ttl.id;

For this table: 对于此表:

  CREATE TABLE  haha_title_lists  (
     id  int(11) unsigned NOT NULL AUTO_INCREMENT,
     name  varchar(255) DEFAULT NULL,
     isbn  varchar(15) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
     created_at  datetime NOT NULL,
     updated_at  datetime NOT NULL,
     user_id  int(11) DEFAULT NULL,
     list_note  text,
     retailer_nomination_list  int(11) DEFAULT NULL,
    PRIMARY KEY ( id )
  ) ENGINE=InnoDB AUTO_INCREMENT=460 DEFAULT CHARSET=utf8

I would expect the PRIMARY KEY to be used, since this table only matches on id. 我希望使用PRIMARY KEY,因为此表仅在id上匹配。 What would cause the use of a temporary table? 什么会导致使用临时表?

If I run EXPLAIN on this query I get: 如果我对此查询运行EXPLAIN,则会得到:

    +----+-------------+-------+--------+------------------------------------------------------------------------+---------------------------------------+---------+---------------------------------------+------+---------------------------------+
  | id | select_type | table | type   | possible_keys                                                          | key                                   | key_len | ref                                   | rows | Extra                           |
  +----+-------------+-------+--------+------------------------------------------------------------------------+---------------------------------------+---------+---------------------------------------+------+---------------------------------+
  |  1 | SIMPLE      | ttl   | ALL    | PRIMARY                                                                | NULL                                  | NULL    | NULL                                  |  307 | Using temporary; Using filesort |
  |  1 | SIMPLE      | tltu  | ref    | idx_title_list_to_user                                                 | idx_title_list_to_user                | 4       | wawa_ripple_development.ttl.id        |    1 | Using index                     |
  |  1 | SIMPLE      | u     | eq_ref | PRIMARY                                                                | PRIMARY                               | 4       | wawa_ripple_development.tltu.user_id  |    1 | Using index                     |
  |  1 | SIMPLE      | u2    | eq_ref | PRIMARY                                                                | PRIMARY                               | 4       | wawa_ripple_development.tltu.user_id  |    1 | Using index                     |
  |  1 | SIMPLE      | tlb   | ref    | idx_title_list_to_books_title_id,idx_title_list_to_books_title_list_id | idx_title_list_to_books_title_list_id | 4       | wawa_ripple_development.ttl.id        |   49 | Using where                     |
  |  1 | SIMPLE      | ot    | eq_ref | PRIMARY                                                                | PRIMARY                               | 4       | wawa_ripple_development.tlb.title_id  |    1 | Using index                     |
  |  1 | SIMPLE      | ota   | ref    | PRIMARY,title_id                                                       | title_id                              | 4       | wawa_ripple_development.ot.title_id   |    1 | Using where; Using index        |
  |  1 | SIMPLE      | oa    | eq_ref | PRIMARY                                                                | PRIMARY                               | 4       | wawa_ripple_development.ota.author_id |    1 | Using index                     |
  |  1 | SIMPLE      | tlv   | ALL    | NULL                                                                   | NULL                                  | NULL    | NULL                                  |  175 |                                 |
  |  1 | SIMPLE      | tvp   | eq_ref | PRIMARY                                                                | PRIMARY                               | 4       | wawa_ripple_development.tlv.venue_id  |    1 |                                 |
  |  1 | SIMPLE      | tv    | eq_ref | PRIMARY                                                                | PRIMARY                               | 4       | wawa_ripple_development.tvp.venue_id  |    1 |                                 |
  +----+-------------+-------+--------+------------------------------------------------------------------------+---------------------------------------+---------+---------------------------------------+------+---------------------------------+

Why do I get "Using temporary; Using filesort"? 为什么会出现“使用临时;使用文件排序”的提示?

First, some comments... 首先,一些评论...

The "using temp, using filesort" is often on the first line of the EXPLAIN , but the actual position of them could be anywhere. “使用临时文件,使用文件排序”通常位于EXPLAIN的第一行,但是它们的实际位置可以在任何地方。 Furthermore there could be multiple tmps and/or sorts, even for a 1-table query. 此外, 甚至对于一个表的查询,可能会有多个 tmp和/或排序。 For example: ... GROUP BY aaa ORDER BY bbb may use one tmp for grouping and another for sorting. 例如: ... GROUP BY aaa ORDER BY bbb可能使用一个tmp进行分组,而使用另一个tmp进行排序。

In newer versions, you can do EXPLAIN FORMAT=JSON SELECT... to get a blow-by-blow account -- it will be clear there how many tmps and sorts there are. 在较新的版本中,您可以执行EXPLAIN FORMAT=JSON SELECT...以获得逐项打击帐户-显然那里有多少个tmp和排序。

"Filesort" is a misnomer. “文件排序”是用词不当。 In many cases, the data may actually be collected in memory and sorted there. 在许多情况下,数据实际上可能收集在内存中并在那里进行排序。 That is, "no file is harmed in the filming of the query". 即,“在查询的拍摄中没有文件受到损害”。 There are many reasons for deciding (either up-front, or later) to use a disk-based sort; 有很多原因决定(预先或以后)使用基于磁盘的排序。 I won't give those details in this answer. 我不会在此答案中提供这些详细信息。 One way to check is SHOW STATUS LIKE 'Created_tmp%tables'; 一种检查方法是SHOW STATUS LIKE 'Created_tmp%tables'; . Another is via the slowlog. 另一个是通过慢日志。

Only recently have some UNIONs been improved to avoid tmp tables -- in obvious cases where they aren't needed. 直到最近UNIONs 某些 UNIONs进行了改进,以避开tmp表-在明显不需要它们的明显情况下。 Alas, unions are still single-threaded. union,联合仍然是单线程的。

Back to your question... Yes, your GROUP BY applies to the first table. 回到您的问题...是的,您的GROUP BY适用于第一个表。 But, for whatever reason, the optimizer chose to gather the data, then sort. 但是,无论出于何种原因,优化器都选择收集数据,然后进行排序。 The other option would have been to use the PRIMARY KEY(id) for ordering and grouping. 另一个选择是使用PRIMARY KEY(id)进行排序和分组。 Hmmm... I wonder what would happen if you added ORDER BY ttl.id ? 嗯...我想知道如果您添加ORDER BY ttl.id会发生什么? I'm guessing that the Optimizer is focusing on how to do the GROUP BY -- either by filesort or by collecting a hash in ram, and it decided that all the JOINs were too much to think through. 我猜测优化器将重点放在如何进行GROUP BY (通过文件排序还是通过在ram中收集哈希值),并决定所有JOINs都考虑JOINs

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 MySQL查询使用filesort和临时 - MySQL query using filesort and temporary 使用临时变量优化mysql NOT IN查询 - Optimize mysql NOT IN query by using temporary variable MySql,JOIN 和 Group By 查询正在使用临时和文件排序 - MySql , JOIN and Group By query is Using temporary and Filesort MySQL查询使用索引使用临时使用文件排序 - Mysql query using index using filesort using temporary 优化MySQL查询以避免“使用位置;使用临时;使用filesort“ - Optimize MySQL query to avoid “Using where; Using temporary; Using filesort” 如何使用显示为“使用临时”的EXPLAIN优化MySQL查询 使用文件排序” - How to optimize a MySQL query with EXPLAIN showing 'using temporary; using filesort' 优化MySQL查询以避免“使用临时”和“使用文件排序” - Optimizing a MySQL query to avoid “Using temporary” and “Using filesort” MySQL-优化查询以使用临时和文件排序删除 - MySQL - Optimize Query To Remove Using Temporary and Using filesort 优化MySQL查询以避免“使用临时”和“使用文件排序” - Optimizing a MySQL query to avoid “Using temporary” and “Using filesort” 在单个MySQL查询中使用多个临时表(在phpMyAdmin中有效,但不适用于PHP) - Using multiple temporary tables in a single MySQL query (works in phpMyAdmin, but not PHP)
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM