MySQL · 特性分析 · 內部暫存資料表

來源:互聯網
上載者:User

標籤:

http://mysql.taobao.org/monthly/2016/06/07/#rdMySQL中的兩種暫存資料表外部暫存資料表

通過CREATE TEMPORARY TABLE 建立的暫存資料表,這種暫存資料表稱為外部暫存資料表。這種暫存資料表只對目前使用者可見,當前會話結束的時候,該暫存資料表會自動關閉。這種暫存資料表的命名與非暫存資料表可以同名(同名後非暫存資料表將對當前會話不可見,直到暫存資料表被刪除)。

內部暫存資料表

內部暫存資料表是一種特殊輕量級的暫存資料表,用來進行效能最佳化。這種暫存資料表會被MySQL自動建立並用來儲存某些操作的中間結果。這些操作可能包括在最佳化階段或者執行階段。這種內部表對使用者來說是不可見的,但是通過EXPLAIN或者SHOW STATUS可以查看MYSQL是否使用了內部暫存資料表用來協助完成某個操作。內部暫存資料表在SQL語句的最佳化過程中扮演著非常重要的角色, MySQL中的很多操作都要依賴於內部暫存資料表來進行最佳化。但是使用內部暫存資料表需要建立表以及中間資料的存取代價,所以使用者在寫SQL語句的時候應該盡量的去避免使用暫存資料表。

內部暫存資料表有兩種類型:一種是HEAP暫存資料表,這種暫存資料表的所有資料都會存在記憶體中,對於這種表的操作不需要IO操作。另一種是OnDisk暫存資料表,顧名思義,這種暫存資料表會將資料存放區在磁碟上。OnDisk暫存資料表用來處理中間結果比較大的操作。如果HEAP暫存資料表儲存的資料大於MAX_HEAP_TABLE_SIZE(詳情請參考MySQL手冊中系統變數部分),HEAP暫存資料表將會被自動轉換成OnDisk暫存資料表。OnDisk暫存資料表在5.7中可以通過INTERNAL_TMP_DISK_STORAGE_ENGINE系統變數選擇使用MyISAM引擎或者InnoDB引擎。

本篇文章主要介紹哪些操作可能會利用到內部暫存資料表。如果使用者在書寫SQL語句的時候能夠盡量少的使用內部暫存資料表進行查詢最佳化,將有效提高查詢執行的效率。

首先我們定義一個表t1,
CREATE TABLE t1( a int, b int); INSERT INTO t1 VALUES(1,2),(3,4);

下面所有的操作都是基於表t1進行舉例的。

  • 在SQL語句中使用SQL_BUFFER_RESULT hint

SQL_BUFFER_RESULT主要用來讓MySQL儘早的釋放表上的鎖。因為如果資料量很大的話,需要較長時間將資料發送到用戶端,通過將資料緩衝到暫存資料表中可以有效減少讀鎖對錶的佔用時間。
例如:

mysql> explain format=json select SQL_BUFFER_RESULT * from t1;EXPLAIN{  "query_block": {"select_id": 1,"cost_info": {  "query_cost": "2.00"},"buffer_result": {  "using_temporary_table": true,  "table": {"table_name": "t1","access_type": "ALL",...
  • 如果SQL語句中包含了DERIVED_TABLE。

在5.7中,由於採用了新的最佳化方式,我們需要使用 set optimizer_switch=’derived_merge=off’來禁止derived table合并到外層的Query中。
例如:

mysql> explain format=json select * from (select * from t1) as tt;EXPLAIN{  "query_block": {"select_id": 1,"cost_info": {  "query_cost": "2.40"},"table": {  "table_name": "tt",  "access_type": "ALL",  ...  "materialized_from_subquery": {"using_temporary_table": true,...
  • 如果我們查詢系統資料表的話,系統資料表的資料將被儲存到內部暫存資料表中。

我們當前不能使用EXPLAIN來查看是否讀取系統資料表資料需要利用到內部暫存資料表,但是可以通過SHOW STATUS來查看是否利用到了內部暫存資料表。
例如:

mysql> select * from information_schema.character_sets;mysql> show status like ‘CREATE%‘;
  • 如果DISTINCT語句沒有被最佳化掉,即DISTINCT語句被最佳化轉換為GROUP BY操作或者利用UNIQUE INDEX消除DISTINCT, 內部暫存資料表將會被使用。
mysql> explain format=json select distinct a from t1;EXPLAIN{{  "query_block": {"select_id": 1,"cost_info": {  "query_cost": "1.60"},"duplicates_removal": {  "using_temporary_table": true,...
  • 如果查詢帶有ORDER BY語句,並且不能被最佳化掉。下面幾種情況會利用到內部暫存資料表緩衝中間資料,然後對中間資料進行排序。

1)如果串連表使用BNL(Batched Nestloop)/BKA(Batched Key Access)
例如:

1))BNL預設是開啟的

mysql> explain format=json select * from t1, t1 as t2 order by t1.a;EXPLAIN{  "query_block": {  "select_id": 1,  "cost_info": {"query_cost": "22.00"  },  "ordering_operation": {"using_temporary_table": true,  ...

2))關掉BNL後,ORDER BY將直接使用filesort。

mysql> set optimizer_switch=‘block_nested_loop=off‘;Query OK, 0 rows affected (0.00 sec)mysql> explain format=json select * from t1, t1 as t2 order by t1.a;EXPLAIN{   "query_block": {"select_id": 1,"cost_info": {  "query_cost": "25.00"},"ordering_operation": {  "using_filesort": true,...

2)ORDER BY的列不屬於執行計畫中第一個串連表的列。
例如:

mysql> explain format=json select * from t as t1, t as t2 order by t2.a;EXPLAIN{   "query_block": {"select_id": 1,"cost_info": {  "query_cost": "25.00"},"ordering_operation": {  "using_temporary_table": true,...

3)如果ORDER BY的運算式是個複雜運算式。

那麼什麼樣的ORDER BY運算式,MySQL認為是複雜運算式呢?

1))如果排序運算式是SP或者UDF。
例如:

drop function if exists func1;delimiter |create function func1(x int)returns int deterministicbegindeclare z1, z2 int;set z1 = x;set z2 = z1+2;return z2;end|delimiter ;explain format=json select * from t1 order by func1(a);{"query_block": {"select_id": 1,"cost_info": {  "query_cost": "2.20"},"ordering_operation": {  "using_temporary_table": true,...

2))ORDER BY的列包含聚集合函式

為了簡化執行計畫,我們利用INDEX來最佳化GROUP BY語句。
例如:

  create index idx1 on t1(a);  explain format=json SELECt a FROM t1 group by a order by sum(a);  | {   "query_block": {"select_id": 1,"cost_info": {  "query_cost": "1.20"},"ordering_operation": {  "using_temporary_table": true,  "using_filesort": true,  "grouping_operation": {"using_filesort": false,...  drop index idx1 on t1;

3))ORDER BY的列中包含有SCALAR SUBQUERY,當然該SCALAR SUBQUERY沒有被最佳化掉。
例如:

explain format=json select (select rand() from t1 limit 1) as a from t1 order by a;| {  "query_block": {"select_id": 1,"cost_info": {  "query_cost": "1.20"},"ordering_operation": {  "using_temporary_table": true,  "using_filesort": true,...

4) 如果查詢既帶有ORDER BY同時也有GROUP BY語句,但是兩個語句使用的列不相同。

注意: 如果是5.7,我們需要將sql_mode設定為非only_full_group_by模式,否則會報錯。

同樣為了簡化執行計畫,我們利用INDEX來最佳化GROUP BY語句。
例如:

set sql_mode=‘‘;create index idx1 on t1(b);explain format=json select t1.a from t1 group by t1.b order by 1;| { "query_block": {"select_id": 1,"cost_info": {  "query_cost": "1.40"},"ordering_operation": {  "using_temporary_table": true,  "using_filesort": true,  "grouping_operation": {"using_filesort": false,...drop index idx1 on t1;
  • 如果查詢帶有GROUP BY語句,並且不能被最佳化掉。下面幾種情況會利用到內部暫存資料表緩衝中間資料,然後對中間資料進行GROUP BY。

1)如果串連表使用BNL(Batched Nestloop)/BKA(Batched Key Access)。
例如:

explain format=json select t2.a from t1, t1 as t2 group by t1.a;| {"query_block": {"select_id": 1,"cost_info": {  "query_cost": "8.20"},"grouping_operation": {  "using_temporary_table": true,  "using_filesort": true,  "cost_info": {"sort_cost": "4.00"...

2) 如果GROUP BY的列不屬於執行計畫中的第一個串連表。
例如:

explain format=json select t2.a from t1, t1 as t2 group by t2.a;| {"query_block": {"select_id": 1,"cost_info": {  "query_cost": "8.20"},"grouping_operation": {  "using_temporary_table": true,  "using_filesort": true,  "nested_loop": [...

3) 如果GROUP BY語句使用的列與ORDER BY語句使用的列不同。
例如:

set sql_mode=‘‘;explain format=json select t1.a from t1 group by t1.b order by t1.a;| {   "query_block": {"select_id": 1,"cost_info": {  "query_cost": "1.40"},"ordering_operation": {  "using_filesort": true,  "grouping_operation": {"using_temporary_table": true,"using_filesort": false,...

4) 如果GROUP BY帶有ROLLUP並且是基於多表外串連。
例如:

explain format=json select sum(t1.a) from t1 left join t1 as t2 on true group by t1.a with rollup;| {"query_block": {"select_id": 1,"cost_info": {  "query_cost": "7.20"},"grouping_operation": {  "using_temporary_table": true,  "using_filesort": true,  "cost_info": {"sort_cost": "4.00"  },...

5) 如果GROUP BY語句使用的列來自於SCALAR SUBQUERY,並且沒有被最佳化掉。
例如:

explain format=json select (select avg(a) from t1) as a from t1 group by a;| {"query_block": {"select_id": 1,"cost_info": {  "query_cost": "3.40"},"grouping_operation": {  "using_temporary_table": true,  "using_filesort": true,  "cost_info": {"sort_cost": "2.00"  },...
  • IN運算式轉換為semi-join進行最佳化
    1) 如果semi-join執行方式為Materialization
    例如:
set optimizer_switch=‘firstmatch=off,duplicateweedout=off‘;explain format=json select * from t1 where a in (select b from t1);| {"query_block": {"select_id": 1,"cost_info": {  "query_cost": "5.60"},"nested_loop": [  { "rows_examined_per_scan": 1,  "materialized_from_subquery": {"using_temporary_table": true,"query_block": {  "table": {"table_name": "t1","access_type": "ALL",... 

2) 如果semi-join執行方式為Duplicate Weedout
例如:

set optimizer_switch=‘firstmatch=off‘;explain format=json select * from t1 where a in (select b from t1); | {"query_block": {"select_id": 1,"cost_info": {  "query_cost": "4.80"},"duplicates_removal": {  "using_temporary_table": true,  "nested_loop": [{...
  • 如果查詢語句帶有UNION,MySQL將利用內部暫存資料表協助UNION操作消除重複。
    例如:
explain format=json select * from t1 union select * from t1;| {"query_block": {"union_result": {  "using_temporary_table": true,  "table_name": "<union1,2>",...
  • 如果查詢語句使用多表更新。
    這裡Explain不能看到內部暫存資料表被利用,所以需要查看status。
    例如:
update t1, t1 as t2 set t1.a=3;show status like ‘CREATE%‘;
  • 如果聚集合函式中包含如下函數,內部暫存資料表也會被利用。
1) count(distinct *)例如:explain format=json select count(distinct a) from t1;2) group_concat例如:explain format=json select group_concat(b) from t1;

總之,上面列出了10種情況,MySQL將利用內部暫存資料表進行中間結果緩衝,如果資料量比較大的話,內部暫存資料表將會把資料存放區在磁碟上,這樣顯然會對效能有所影響。為了儘可能的減少效能損失,我們需要盡量避免上述情況的出現。

MySQL · 特性分析 · 內部暫存資料表

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.