/* If result table is small; use a heap */
  /* future: storage engine selection can be made dynamic? */
  if ( blob_count || using_unique_constraint
      || ( thd->variables .big_tables && !( select_options & SELECT_SMALL_RESULT ))
      || ( select_options & TMP_TABLE_FORCE_MYISAM ))
  {
    share->db_plugin = ha_lock_engine(0, myisam_hton);
    table->file = get_new_handler( share, &table ->mem_root,
                                 share->db_type ());
    if (group &&
          ( param->group_parts > table-> file->max_key_parts () ||
           param->group_length > table-> file->max_key_length ()))
      using_unique_constraint=1;
  }
  else
  {
    share->db_plugin = ha_lock_engine(0, heap_hton);
    table->file = get_new_handler( share, &table ->mem_root,
                                 share->db_type ());
  }


  代码地址:sql_select.cc:11224,函数:create_myisam_from_heap(),位置:sql_select.cc:11287


/*
    copy all old rows from heap table to MyISAM table
    This is the only code that uses record[1] to read/write but this
    is safe as this is a temporary MyISAM table without timestamp/autoincrement
    or partitioning.
  */
  while (! table->file ->rnd_next( new_table.record [1]))
  {
    write_err= new_table .file-> ha_write_row(new_table .record[1]);
    DBUG_EXECUTE_IF("raise_error" , write_err= HA_ERR_FOUND_DUPP_KEY ;);
    if (write_err )
      goto err ;
  }

  官方文档相关内容

  以上内容只是源码表面的问题,通过查询MySQL的官方文档,得到了更为权威的官方信息。

  临时表创建的条件:

  1、如果order by条件和group by的条件不一样,或者order by或group by的不是join队列中的第一个表的字段。

  2、DISTINCT联合order by条件的查询。

  3、如果使用了SQL_SMALL_RESULT选项,MySQL使用memory临时表,否则,查询询结果需要存储到磁盘。

  临时表不使用内存表的原则:

  1、表中有BLOB或TEXT类型。

  2、group by或distinct条件中的字段大于512个字节。

  3、如果使用了UNION或UNION ALL,任何查询列表中的字段大于512个字节。

  此外,使用内存表大为tmp_table_size和max_heap_table_size的小值。如果超过该值,转化为myisam存储引擎存储到磁盘。