qileilove

          blog已經轉移至github,大家請訪問 http://qaseven.github.io/

          MySQL內部臨時表策略

            通過對MySQL數據庫源碼的跟蹤和調試,以及參考MySQL官方文檔,對MySQL內部臨時表使用策略進行整理,以便于更加深入的理解。

            使用內部臨時表條件

            MySQL內部臨時表的使用有一定的策略,從源碼中關于SQL查詢是否需要內部臨時表??梢钥偨Y如下:

            1、DISTINCT查詢,但是簡單的DISTINCT查詢,比如對primary key、unique key等DISTINCT查詢時,查詢優化器會將DISTINCT條件優化,去除DISTINCT條件,也不會創建臨時表;

            2、不是第一個表的字段使用ORDER BY 或者GROUP BY;

            3、ORDER BY和GROUP BY使用不同的順序;

            4、用戶需要緩存結果;

            5、ROLLUP查詢。

            源碼如下所示

            代碼地址:sql_select.cc:854,函數:JOIN::optimize(),位置:sql_select.cc:1399

          /*
              Check if we need to create a temporary table.
              This has to be done if all tables are not already read (const tables)
              and one of the following conditions holds:
              - We are using DISTINCT (simple distinct's are already optimized away)
              - We are using an ORDER BY or GROUP BY on fields not in the first table
              - We are using different ORDER BY and GROUP BY orders
              - The user wants us to buffer the result.
              When the WITH ROLLUP modifier is present, we cannot skip temporary table
              creation for the DISTINCT clause just because there are only const tables.
            */
            need_tmp= (( const_tables != tables &&
                         (( select_distinct || !simple_order || !simple_group) ||
                          ( group_list && order ) ||
                          test(select_options & OPTION_BUFFER_RESULT))) ||
                       ( rollup.state != ROLLUP:: STATE_NONE && select_distinct ));

            內部臨時表使用原則

            但是使用了內部臨時表,那么他是怎么存儲的呢?原則是這樣的:

            1、當查詢結果較小的情況下,使用heap存儲引擎進行存儲。也就是說在內存中存儲查詢結果。

            2、當查詢結果較大的情況下,使用myisam存儲引擎進行存儲。

            3、當查詢結果最初較小,但是不斷增大的情況下,將會有從heap存儲引擎轉化為myisam存儲引擎存儲查詢結果。

            什么情況算是查詢結果較小呢?從源碼中if的幾個參數可以看出:

            1、有blob字段的情況;

            2、使用唯一限制的情況;

            3、當前表定義為大表的情況;

            4、查詢結果的選項為小結果集的情況;

            5、查詢結果的選項為強制使用myisam的情況

            源碼如下所示

            代碼地址:sql_select.cc:10229,函數:create_tmp_table(),位置:sql_select.cc:10557

          /* 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存儲引擎存儲到磁盤。


          posted on 2012-08-10 09:55 順其自然EVO 閱讀(886) 評論(0)  編輯  收藏 所屬分類: 數據庫

          <2012年8月>
          2930311234
          567891011
          12131415161718
          19202122232425
          2627282930311
          2345678

          導航

          統計

          常用鏈接

          留言簿(55)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 延寿县| 搜索| 绥芬河市| 山东省| 安达市| 阿克| 曲阜市| 临夏市| 恩施市| 竹北市| 临海市| 广德县| 启东市| 屏山县| 茶陵县| 汉川市| 乌拉特前旗| 宁化县| 阜平县| 福海县| 紫金县| 乌拉特后旗| 秦皇岛市| 离岛区| 洞口县| 安康市| 当涂县| 禄劝| 景德镇市| 肃北| 无锡市| 江北区| 宜川县| 故城县| 武夷山市| 应城市| 阆中市| 定安县| 息烽县| 柳江县| 荣成市|