查看命令html
a. 查看所使用的MySQL如今已提供什麼存儲引擎:java
mysql> show engines;mysql
b. 查看所使用的MySQL當前默認的存儲引擎:ios
mysql> show variables like '%storage_engine%';程序員
MyISAM和InnoDB兩種存儲引擎的區別算法
對比項 | MyISAM | InnoDB |
---|---|---|
主外鍵 | 不支持 | 支持 |
事務 | 不支持 | 支持 |
行表鎖 | 表鎖,即便操縱一條記錄也會鎖住整個表,不適合高併發的操做 | 行鎖,操做時只鎖某一行,不對其餘行有影響,適合高併發的操做 |
緩存 | 只緩存索引,不緩存真實數據 | 不只緩存索引還要緩存真實數據,對內存要求較高,並且內存大小對性能有決定性的影響 |
表空間 | 小 | 大 |
關注點 | 性能 | 事務 |
默認安裝 | Y | Y |
事務隔離級別
「髒讀」、「不可重複讀」和「幻讀」,其實都是數據庫讀一致性問題,必須由數據庫提供必定的事務隔離機制來解決。sql
讀數據一致性及容許的併發反作用 | 讀數據一致性 | 髒讀 | 不可重複讀 | 幻讀 |
---|---|---|---|---|
Read uncommitted | 最低級別,只能保證不讀取物理上損壞的數據 | 是 | 是 | 是 |
Read committed | 語句級 | 否 | 是 | 是 |
Repeatable read | 事務級 | 否 | 否 | 是 |
Serializable | 最高級別,事務級 | 否 | 否 | 否 |
數據庫的事務隔離越嚴格,併發反作用越小,但付出的代價也就越大,由於事務隔離實質上就是使事務在必定程度上,「串行化」進行,這顯然與「併發」是矛盾的。同時,不一樣的應用對讀一致性和事務隔離程度的要求也是不一樣的,好比許多應用對「不可重複讀」和「幻讀」並不敏感,可能更關心數據併發訪問的能力。
查看MySQL的事務隔離級別:show variables like 'tx_isolation';
數據庫
包括但不限於下列狀況:緩存
MySQL官方對索引的定義爲:索引(Index)是幫助MySQL高效獲取數據的數據結構。能夠獲得索引的本質:索引是數據結構。
索引的目的在於提升查詢效率,能夠類比字典,好比:若是要查「MySQL」這個單詞,咱們確定須要定爲到m字母,而後從上往下找到y字母,再找到剩下的s、q、l。若是沒有索引,那麼你可能須要a--z,若是我想找到Java開頭的單詞呢?或者Oracle開頭的單詞呢?是否是以爲若是沒有索引,這個事情根本沒法完成?
你能夠簡單理解爲「排好序的快速查找的數據結構」。服務器
詳解
在數據以外,數據庫系統還維護着知足特定查找算法的數據結構,這些數據結構以某種方式引用(指向)數據,這樣就能夠在這些數據結構上實現高級查找算法。這種數據結構,就是索引。下圖就是一種可能的索引方式示例:
爲了加快Col2的查找,能夠維護一個右邊所示的二叉查找樹,每一個節點分別包含索引鍵值和一個指向對應數據的記錄物理地址的指針,這樣就能夠運用二叉查找在必定的複雜度內獲取到相應數據,從而快速的檢索出符合條件的記錄。
結論
數據自己以外,數據庫還維護着一個知足特定查找算法的數據結構,這些數據結構以某種方式指向數據,這樣就能夠在這些數據結構的基礎上實現高級算法,這種數據結構就是索引。
通常來講,索引自己也很大,不可能所有存儲在內存中,所以索引每每以索引文件的形式存儲在磁盤上。
咱們日常所說的索引,若是沒有特別指明,都是指B樹(多路搜索樹,並不必定是二叉樹)結構組織的索引。其中彙集索引,次要索引,覆蓋索引,複合索引,前綴索引,惟一索引默認都是使用B+數索引,統稱索引。固然,除了B+樹這種類型的索引以外,還有哈希索引(hash index)等。
優點
相似大學圖書館創建書目索引,提升數據檢索的效率,下降數據庫的IO成本。經過索引列對數據進行排序,下降數據排序的成本,下降了CPU的消耗。
劣勢
實際上索引也是一張表,該表保存了主鍵與索引字段,並指向實體表的記錄,因此索引列也是要佔用空間的。
雖然索引大大提升了查詢速度,同時卻會下降更新表的速度,如對錶進行INSERT
、UPDATE
和DELETE
。由於更新表時,MySQL不只要保存數據,還要保存一下索引文件每次更新添加了索引列的字段。
索引只是提升效率的一個因素,若是你的MySQL有大數據量的表,就須要花時間創建最優秀的索引,或優化查詢。
MySQL索引分類
創建複合索引優於創建單值索引。通常而言,一張表最多建5個索引
基本語法
CREATE [UNIQUE] INDEX indexName ON mytable(columnname(length));
ALTER mytable ADD [UNIQUE] INDEX [indexName] ON (columnname(length));
DROP INDEX [indexName] ON mytable;
SHOW INDEX FROM table_name;
ALTER TABLE tbl_name ADD PRIMARY KEY(column_list);
該語句添加一個主鍵,這意味着索引值必須是惟一的,且不能爲NULL;ALTER TABLE tbl_name ADD UNIQUE index_name(column_list);
這條語句建立索引的值必須是惟一的(除了NULL外,NULL可能會出現屢次);ALTER TABLE tbl_name ADD INDEX index_name(column_list);
添加普通索引,索引值可出現屢次;ALTER TABLE tbl_name ADD FULLTEXT index_name(column_list);
該語句指定了索引爲FULLTEXT,用於全文索引。Btree
儘可能增長檢索廣度,不增長深度。檢索原理:
R-Tree
INSERT
、UPDATE
和DELETE
。由於更新表時,MySQL不只要保存數據,還要保存一下索引文件。MySQL Query Optimizer
時,MySQL Query Optimizer
首先會對整條Query進行優化,處理掉一些常量表達式的預算,直接換算成常量值。並對Query中的查詢條件進行簡化和轉換,如去掉一些無用或顯而易見的條件、結構調整等。而後分析Query中的Hint信息(若是有),看現實Hint信息是否能夠徹底肯定該Query的執行計劃。若是沒有Hint或Hint信息還不足以徹底肯定執行計劃,則會讀取所涉及對象的統計信息,根據Query進行寫相應的計算分析,而後再得出最後的執行計劃。top
, free
, iostat
和vmstat
來查看系統的性能狀態。使用EXPLAIN關鍵字能夠模擬優化器執行SQL查詢語句,從而知道MySQL是如何處理你的SQL語句的。分析你的查詢語句或是表結構的性能瓶頸。
官網介紹
包含的信息
id
select
查詢的序列號,包含一組數字,表示查詢中執行select
子句或操做表的順序。包含三種狀況:
id
相同,執行順序由上至下
id
不一樣,若是是子查詢,id
的序號會遞增,id
值越大優先級越高,越先被執行
id
相同和不一樣,同時存在
id
若是相同,能夠認爲是一組,從上往下順序執行,在全部組中,id
值越大,優先級越高,越先執行。select_type
SIMPLE
,PRIMARY
,SUBQUERY
,DERIVED
,UNION
,UNION RESULT
,主要是用於區別普通查詢、聯合查詢、子查詢等複雜查詢。
select
查詢,查詢中不包含子查詢或者UNION
PRIMARY
SELECT
或者WHERE
列表中包含了子查詢FROM
列表中包含的子查詢被標記爲DERIVED
(衍生),MySQL會遞歸執行這些子查詢,把結果放在臨時表裏SELECT
出如今UNION
以後,則被標記爲UNION
,若UNION
包含在FROM
子句的子查詢中,外層SELECT將被標記爲:DERIVED
UNION
表獲取結果的SELECT
table
type
ALL
,index
,range
,ref
,eq_ref
,const,system
,NULL
。system > const > eq_ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL
system > const > eq_ref > ref > range > index > ALL
const
類型的特例,平時不會出現,這個也能夠忽略不計const
用於比較primary key
或者unique
索引,由於只匹配一行數據,因此很快,如將主鍵置於where
列表中,MySQL就能將該查詢轉換爲一個常量eq_ref:惟一性索引掃描,對於每一個索引鍵,表中只有一條記錄與之匹配。常見於主鍵或惟一索引掃描
ref:非惟一性索引掃描,返回匹配某個單獨值的全部行。
本質上也是上也是一種索引訪問,它返回全部匹配某個單獨值的行,然而,它可能會找到多個符合條件的行,因此它應該屬於查找和掃描的混合體
range:只檢索給定範圍的行,使用一個索引來選擇行。
key
列顯示使用了哪一個索引,通常就是在你的where
語句中出現了between
、<
、>
、in
等的查詢,這種範圍掃描索引掃描比全表掃描要好,由於它只須要開始於索引的某一點,而結束語另外一點,不用掃描所有索引。以下:
Full Index Scan
,index
與ALL
的區別爲index
類型只遍歷索引樹,這一般比ALL
塊,由於索引文件一般比數據文件小。(也就是說雖然ALL
和index
都是讀全表,但index
是從索引中讀取的,而ALL是從硬盤中讀的)Full Table Scan
,將遍歷全表以找到匹配的行possible_keys
key
實際使用的索引。若是爲NULL
,則沒有使用索引。查詢中若使用了覆蓋索引,則該索引僅出如今key
列表中。以下:
先創建索引:
create index idx_col1_col2 on t2(col1, col2);
而後使用explain語句分析下列SQL語句:
key_len
key_len
顯示的值爲索引字段的最大可能長度,並不是實際使用長度,即key_len是根據表定義計算而得,不是經過表內檢索出的。ref
idx_col1_col2
被充分使用,col1
匹配t2表的col1
,col2匹配了一個常量,即‘ac’。rows
根據表統計信息及索引選用狀況,大體估算出找到所需的記錄所須要讀取的行數。以下,觀察創建索引先後rows的變化:
Extra
Using filesort
,該SQL語句會執行得比較慢,須要對其進行優化。order by
和分組查詢group by
。Using temporary
,那麼該SQL語句會更慢,需對其進行優化。select
操做中使用了覆蓋索引(Covering Index),避免訪問了表的數據行,效率不錯!若是同時出現Using where
,代表索引被用來執行索引鍵值的查找;若是沒有同時出現Using where
,代表索引被用來讀取數據而非執行查找動做。Using where
,代表索引被用來執行索引鍵值的查找;Using where
,代表索引用來讀取數據而非執行查找動做。select
的數據列只用從索引中就可以取得,沒必要讀取數據行,MySQL能夠利用索引返回select
列表中的字段,而沒必要根據索引再次讀取數據文件,換句話說查詢列要被所建的索引覆蓋。select
列表中只取出須要的列,不可select *
,由於若是將全部字段一塊兒作索引會致使索引文件過大,查詢性能降低。where
過濾。impossible where:where
子句的值老是false
,不能用來獲取任何元組。如:
GROUP BY
子句的狀況下,基於索引優化MIN/MAX操做或者對於MyISAM存儲引擎優化COUNT(*)
操做,沒必要等到執行階段再進行計算,查詢執行計劃生成的階段即完成優化。distinct:(出現頻率很小)優化distinct
操做,在找到第一匹配的元組後即中止找一樣的動做。
第一行(執行順序4):id
列爲1,表示是union
裏的第一個select
,select_type
列的primary
表示該查詢爲外層查詢,table
列被標記爲<derived3>
,表示查詢結果裏來自一個衍生表,其中derived3
中3表明該查詢衍生自第三個select
查詢,即id
爲3的select
。select d1.name ......
第二行(執行順序2):id
爲3,是整個查詢中第三個select
的一部分,因查詢包含在from
中,因此爲derived
。select id, name from t1 where other_column="
第三行(執行順序3):select
列表中的子查詢select_type
爲subquery
,爲整個查詢中的第二個select
。select id from t3
第四行(執行順序1):select_type
爲union
,說明第四個select
是union
裏的第二個select
,最早執行。select name, id from t2
第五行(執行順序5):表明從union
的臨時表中讀取行的階段,table
列的<union1,4>
表示用第一個和第四個select
的結果進行。
explain select id, author_id from article where category_id = 1 and comments > 1 order by views desc limit 1;
type
是ALL
,即最壞的狀況,Extra
裏還出現了Using filesort
,也是最壞的狀況。必需要進行優化。alter table article add index idx_article_ccv(category_id, comments, views);
或create index idx_article_ccv on article(category_id, comments, views);
explain select id, author_id from article where category_id = 1 and comments > 1 order by views desc limit 1;
type
爲range
,這是能夠忍受的。可是extra
裏使用Using filesort
還是沒法接受的。category_id
,若是遇到相同的category_id
,則再排序comments
,若是遇到相同的comments
則再排序views。comments
字段在聯合索引裏處於中間位置時,因comments > 1
條件是一個範圍值(所謂range
),MySQL沒法利用索引再對後面的views
部分進行檢索,即range
類型查詢字段後面的索引無效。
drop index idx_article_ccv on article;
alter table article add index idx_article_cv(category_id, views);
或create index idx_article_cv on article(category_id, views);
explain
explain select id, author_id from article where category_id = 1 and comments > 1 order by views desc limit 1;
type
變爲了ref
,Extra
中的Using filesort
也消失了,結果很是理想。insert into class(card) values(floor(1 + (rand() * 20)));
insert into book(card) values(floor(1 + (rand() * 20)));
explain select * from class left join book on class.card = book.card;
結論:type中有ALL。
添加索引進行優化:alter table book add index y(card);
再次進行explain分析:
能夠看到第二行的type
變爲了ref
,rows
優化也比較明顯。 這是由左鏈接特性決定的。left join
條件用於肯定如何從右表搜索行,左邊必定都有,因此右邊是咱們的關鍵點,必定須要創建索引。
刪除舊索引,而後創建新的索引,再進行第3次explain
insert into phone(card) values(floor(1 + (rand() * 20)));
alter table phone add index z(card);
alter table book add index y(card);
後兩行的type
都是ref
,且總的rows
優化很好,效果不錯,所以索引最好設置在須要常常查詢的字段中。
Join語句的優化
Join
語句中的NestedLoop
的循環總次數:「永遠用小結果集驅動大的結果集」;NestedLoop
的內層循環;Join
條件字段已經被索引;Join
條件字段被索引且內存資源充足的前提下,不要太吝嗇JoinBuffer
的設置。insert into staffs(name, age, pos, add_time) values('z3', 22, 'manager', now());
insert into staffs(name, age, pos, add_time) values('july', 23, 'dev', now());
insert into staffs(name, age, pos, add_time) values('tom', 23, 'dev', now());
ALTER TABLE staffs ADD INDEX idx_staffs_nameAgePos(name,age,pos);
全值匹配
不在索引列上作任何操做(計算、函數、(自動or手動)類型轉換),會致使索引失效而轉向全表掃描
存儲引擎不能使用索引中範圍條件右邊的列
is null
,is not null
也沒法使用索引‘%abc…’
)MySQL索引失效會變成全表掃描的操做explain select id from tbl_user where name like '%aa%;
explain select name from tbl_user where name like '%aa%;
explain select age from tbl_user where name like '%aa%;
explain select id, name from tbl_user where name like '%aa%;
explain select id, name, age from tbl_user where name like '%aa%;
explain select name, age from tbl_user where name like '%aa%;
explain select * from tbl_user where name like '%aa%;
explain select id, name, age, email from tbl_user where name like '%aa%;
create index idx_user_nameAge on tbl_user(name, age);
explain
,除了最後兩條select *
即查詢列多出了索引外的email
字段,其他都利用了覆蓋索引或直接使用了主鍵索引,效果都會挺好。小總結
全值匹配我最愛,最左前綴要遵照;
帶頭大哥不能死,中間兄弟不能斷;
索引列上少計算,範圍以後全失效;
Like百分寫最右,覆蓋索引不寫星;
不等空值還有or,索引失效要少用;
VAR引號不可丟,SQL高級也不難。
假設index(a, b, c):下表中的各類狀況,可自行試驗。
where語句 | 索引是否被使用 | |
---|---|---|
where a = 3 | Y,使用到a | |
where a = 3 and b = 5 | Y,使用到a,b | |
where a = 3 and b = 5 and c = 4 | Y,使用到a,b,c | |
where b = 3 或者 where b = 3 and c = 4 或者 where c = 4 | N | |
where a = 3 或者 c = 5 | 使用到a,可是c不能夠,b中間斷了 | |
where a = 3 and b > 4 and c = 5 | 使用到a和b,c不能用在範圍以後,b斷了 | |
where a = 3 and b like 'kk%' and c = 4 | Y,使用到a,b,c | |
where a = 3 and b like '%kk' and c = 4 | Y,只用到a | |
where a = 3 and b like '%kk%' and c = 4 | Y,只用到a | |
where a = 3 and b like 'k%kk%' and c = 4 | Y,使用到a,b,c |
小表驅動大表,即小的數據集驅動大的數據集。
select * from A where id in (select id from B) 等價於 for select id from B for select * from A where A.id = B.id
當B表的數據集必須小於A表的數據集時,用in優於exists。
select * from A where exists (select 1 from B where B.id = A.id) 等價於 for select * from A for select * from B where B.id = A.id
當A表的數據集系小於B表的數據集時,用exists優於in。
注意:A表與B表的id字段應創建索引。
select ... from table where exists (subquery);
exists(subquery)
只返回true或false,所以子查詢中的select *
也能夠是select 1
或其餘,官方說法是實際執行時會忽略select
清單,所以沒有區別exists
子查詢的實際執行過程可能通過了優化而不是咱們理解上的逐條對比,若是擔心效率問題,可進行實際檢驗以肯定是否有效率問題exists
子查詢每每也能夠用條件表達式、其餘子查詢或者join
來替代,何種最優須要具體問題具體分析order by
子句,儘可能使用index
方式排序,避免使用filesort
方式排序
建表SQL + 添加數據 + 創建索引
case
filesort
和index
,index
效率高,它指MySQL掃描索引自己完成排序,filesort
方式效率較低order by
知足兩種狀況,會使用index方式排序:
order by
語句使用索引最左前列where
子句與order by
子句條件列組合知足索引最左前列filesort
有兩種算法,MySQL就要啓動雙路排序和單路排序
order by
列,對他們進行排序,而後掃描已經排序好的列表,按照列表中的值從新從列表中讀取對應的數據輸出。buffer
進行排序,再從磁盤取其餘字段。order by
列在buffer
對它們進行排序,而後掃描排序後的列表進行輸出,它的效率更快一些,避免了第二次讀取數據。而且把隨機IO變成了順序IO,可是它會使用更多的空間,由於它把每一行都保存在內存中了。sort_buffer
中,方法B比方法A要佔用不少空間,由於方法B是把全部字段都取出,因此有可能取出的數據的總大小超出了sort_buffer
的容量,致使每次只能取sort_buffer
容量大小的數據,進行排序(建立tmp文件,多路合併),排完再去取sort_buffer
容量大小,再排......從而屢次I/O。sort_buffer_size
參數的的設置max_length_for_sort_data
參數的設置order by
的時候,select *
是一個大忌,所以只查詢須要的字段,這點很是重要,在這裏影響的是:
max_length_for_sort_data
並且排序字段不是text
|blob
類型時,會用改進後的算法--單路排序,不然用老算法--多路排序sort_buffer
的容量,超出以後,會建立tmp文件進行合併排序,致使屢次I/O,可是用單路排序算法的風險會更大一些,因此要提升sort_buffer_size
sort_buffer_size
max_length_for_sort_data
sort_buffer_size
的機率就增大,明顯症狀是高的磁盤I/O活動和低的處理器使用率小總結
key:a_b_c(a, b, c)
order by能使用索引最左前綴
order by a
order by a,b
order by a,b,c
order by a desc,b desc,c desc #這個同時都爲降序因此也能夠若是where使用索引的最左前綴定義爲常量,則order by能使用索引
where a=const order by b,c
where a=const and b=const order by c
where a=const order by b,c
where a=const and b>const order by b,c不能使用索引進行排序
order by a asc,b desc,c desc #排序不一致,有升序有降序
where g=const order by b,c #丟失a索引,沒有帶頭大哥
where a=const order by c #丟失b索引
where a in(...) order by b,c #對於排序來講,多個相等條件也是範圍查詢
group by
實質是先排序後進行分組,遵守索引建的最佳左前綴max_length_for_sort_data
參數的設置加增大sort_buffer_size
參數的設置where
高於having
,能寫在where
限定的條件就不要去having
限定了MySQL的慢查詢日誌是MySQL提供的一種日誌記錄,它用來記錄在MySQL中響應時間超過閥值的語句,具體指運行時間超過long_query_time
值的SQL,則會被記錄到慢查詢日誌中。long_query_time
的默認值爲10,意思是運行10秒以上的語句。
用它來查看哪些SQL超出了咱們的最大忍耐時間值,好比一條SQL執行超過5秒鐘,咱們就把它定爲慢SQL,但願能收集超過5秒鐘的SQL,結合以前的explain
進行全面分析。
默認
show varialbes like '%slow_query_log%';
經過執行上條語句,能夠看到,默認狀況下,slow_query_log
的值爲OFF
,表示慢查詢日誌是禁用的。能夠經過設置slow_query_log
的值來開啓。
set global slow_query_log=1;
set global slow_query_log=1
開啓了慢查詢日誌,只對當前數據庫生效,而且若是MySQL重啓後則會失效。my.cnf
(其它系統變量也是如此)my.cnf
文件,[mysqld]下增長或修改參數slow_query_log
和slow_query_log_file
後,而後重啓MySQL服務器。也即,將以下兩行配置進my.cnf
文件slow_query_log=1
slow_query_log_file=/usr/local/mysql/data/chengchangfudeMacBook-Pro-slow.log
slow_query_log_file
,它指定慢查詢日誌文件的存放路徑,系統默認會給一個缺省的文件 host_name_slow.log
(若是沒有指定參數slow_query_log_file
的話)。long_query_time
控制的,默認狀況下long_query_time
的值爲10秒,命令:show variables like 'long_query_time%';
long_query_time
的狀況,並不會被記錄下來。也就是說,在MySQL源碼裏是判斷大於long_query_time
,而非大於等於。show variables like 'long_query_time%';
set global long_query_time=3;
記錄慢查詢並分析
查詢當前系統中有多少條慢查詢記錄
[mysqld]
下配置:在生產環境中,若是要手工分析日誌,查找、分析SQL,顯然是個體力活,MySQL提供了日誌分析工具:mysqldumpslow
。
查看mysqldumpslow
的幫助信息
使用mysqldumpslow --help
命令進行查看
s:是表示按照何種方式排序;
c:訪問次數
l:鎖定時間
r:返回記錄
t:查詢時間
al:平均鎖定時間
ar:平均返回記錄數
at:平均查詢時間
t:即爲返回前面多少條的數據;
g:後邊搭配一個正則匹配模式,大小寫不敏感的;
工做經常使用參考
獲得返回記錄集最多的10個SQL
mysqlddumpslow -s r -t 10 chengchangfudeMacBook-Pro-slow.log
獲得訪問次數最多的10個SQL
mysqlddumpslow -s c -t 10 chengchangfudeMacBook-Pro-slow.log
獲得按照時間排序的前10條裏面含有左鏈接的查詢語句
mysqlddumpslow -s t -t 10 -g "left join" chengchangfudeMacBook-Pro-slow.log
另外建議在使用這些命令時結合|
和more
使用,不然有可能出現爆屏狀況
mysqlddumpslow -s r -t 10 chengchangfudeMacBook-Pro-slow.log | more
Show Profile
是MySQL提供能夠用來分析當前會話中語句執行的資源消耗狀況。能夠用於SQL調優的測量。
官網介紹
默認狀況下,參數處於關閉狀態,並保存最近15次的運行結果,使用set profiling=on;
進行開啓
select * from emp group by id%10 limit 150000;
select * from emp group by id%20 order by 5;
診斷SQL
show profile cpu, block io for query 上一步前面的問題SQL數字號碼;
如:show profile cpu, block io for query 3;
上面詳細列出了一條查詢語句通過的全部的過程。
參數備註:
ALL 顯示全部的開銷信息
BLOCK IO 顯示塊IO相關開銷
CONTEXT SWITCHES 上下文切換相關開銷
CPU 顯示CPU相關開銷信息
IPC 顯示發送和接收相關開銷信息
MEMORY 顯示內存相關開銷信息
PAGE FAULTS 顯示頁面錯誤相關開銷信息
SOURCE 顯示和Source_function,Source_file,Source_line相關的開銷信息
SWAPS 顯示交換次數相關開銷信息
converting HEAP to MyISAM
:查詢結果太大,內存都不夠用了往磁盤上搬了create tmp table
:建立臨時表,拷貝數據到臨時表,用完再刪除copying to tmp table on disk
:把內存中臨時表複製到磁盤,危險!!!locked