?? manual_performance.html
字號:
<p>下面是一些很快的查詢例子: </p>
<pre>mysql> SELECT COUNT(*) FROM tbl_name;
mysql> SELECT MIN(key_part1),MAX(key_part1) FROM tbl_name;
mysql> SELECT MAX(key_part2) FROM tbl_name
WHERE key_part_1=constant;
mysql> SELECT ... FROM tbl_name
ORDER BY key_part1,key_part2,... LIMIT 10;
mysql> SELECT ... FROM tbl_name
ORDER BY key_part1 DESC,key_part2 DESC,... LIMIT 10;
</pre>
<p>下列查詢僅使用索引樹就可解決(假設(shè)索引列是數(shù)字的): </p>
<pre>mysql> SELECT key_part1,key_part2 FROM tbl_name WHERE key_part1=val;
mysql> SELECT COUNT(*) FROM tbl_name
WHERE key_part1=val1 AND key_part2=val2;
mysql> SELECT key_part2 FROM tbl_name GROUP BY key_part1;
</pre>
<p>下列查詢使用索引以排序順序檢索,不用一次另外的排序: </p>
<pre>mysql> SELECT ... FROM tbl_name ORDER BY key_part1,key_part2,...
mysql> SELECT ... FROM tbl_name ORDER BY key_part1 DESC,key_part2 DESC,...
</pre>
<h3><a NAME="LEFT_JOIN_optimization" HREF="manual_toc.html#LEFT_JOIN_optimization">10.5.4
MySQL怎樣優(yōu)化<code>LEFT JOIN</code></a></h3>
<p>在<strong>MySQL</strong><code>中,A LEFT JOIN B</code>實(shí)現(xiàn)如下:
<ul>
<li>表<code>B</code>被設(shè)置為依賴于表<code>A</code>。 </li>
<li>表<code>A</code>被設(shè)置為依賴于所有用在<code>LEFT JOIN</code>條件的表(除<code>B</code>外)。
</li>
<li>所有<code>LEFT JOIN</code>條件被移到<code>WHERE</code>子句中。 </li>
<li>進(jìn)行所有標(biāo)準(zhǔn)的聯(lián)結(jié)優(yōu)化,除了一個(gè)表總是在所有它依賴的表之后被讀取。如果有一個(gè)循環(huán)依賴,<strong>MySQL</strong>將發(fā)出一個(gè)錯(cuò)誤。
</li>
<li>進(jìn)行所有標(biāo)準(zhǔn)的<code>WHERE</code>優(yōu)化。 </li>
<li>如果在<code>A</code>中有一行匹配<code>WHERE</code>子句,但是在<code>B</code>中沒有任何行匹配<code>LEFT
JOIN</code>條件,那么在<code>B</code>中生成所有列設(shè)置為<code>NULL</code>的一行。
</li>
<li>如果你使用<code>LEFT JOIN</code>來找出在某些表中不存在的行并且在<code>WHERE</code>部分你有下列測試:<code>column_name
IS NULL</code>,這里column_name 被聲明為<code>NOT NULL</code>的列,那么<code>MySQL</code>在它已經(jīng)找到了匹配<code>LEFT
JOIN</code>條件的一行后,將停止在更多的行后尋找(對一特定的鍵組合)。
</li>
</ul>
<h3><a NAME="LIMIT_optimization" HREF="manual_toc.html#LIMIT_optimization">10.5.5 MySQL怎樣優(yōu)化<code>LIMIT</code></a></h3>
<p>在一些情況中,當(dāng)你使用<code>LIMIT #</code>而不使用<code>HAVING</code>時(shí),<strong>MySQL</strong>將以不同方式處理查詢。
<ul>
<li>如果你用<code>LIMIT</code>只選擇一些行,當(dāng)<strong>MySQL</strong>一般比較喜歡做完整的表掃描時(shí),它將在一些情況下使用索引。
</li>
<li>如果你使用<code>LIMIT #</code>與<code>ORDER BY</code>,<strong>MySQL</strong>一旦找到了第一個(gè)<code>
#</code> 行,將結(jié)束排序而不是排序整個(gè)表。 </li>
<li>當(dāng)結(jié)合<code>LIMIT #</code>和<code>DISTINCT</code>時(shí),<strong>MySQL</strong>一旦找到<code>#</code>個(gè)唯一的行,它將停止。
</li>
<li>在一些情況下,一個(gè)<code>GROUP BY</code>能通過順序讀取鍵(或在鍵上做排序)來解決,并然后計(jì)算摘要直到鍵值改變。在這種情況下,<code>LIMIT
#</code>將不計(jì)算任何不必要的<code>GROUP</code>。 </li>
</li>
<li><code>LIMIT 0</code>將總是快速返回一個(gè)空集合。這對檢查查詢并且得到結(jié)果列的列類型是有用的。
</li>
<li>臨時(shí)表的大小使用<code>LIMIT #</code>計(jì)算需要多少空間來解決查詢。 </li>
</ul>
<h3><a NAME="Insert_speed" HREF="manual_toc.html#Insert_speed">10.5.6 <code>INSERT</code>查詢的速度</a></h3>
<p>插入一個(gè)記錄的時(shí)間由下列組成:
<ul>
<li>連接:(3) </li>
<li>發(fā)送查詢給服務(wù)器:(2) </li>
<li>分析查詢:(2) </li>
<li>插入記錄:(1 x 記錄大?。?lt;/li>
<li>插入索引:(1 x 索引)</li>
<li>關(guān)閉:(1) </li>
</ul>
<p>這里的數(shù)字有點(diǎn)與總體時(shí)間成正比。這不考慮打開表的初始開銷(它為每個(gè)并發(fā)運(yùn)行的查詢做一次)。
</p>
<p>表的大小以N log N (B 樹)的速度減慢索引的插入。 </p>
<p>加快插入的一些方法:
<ul>
<li>如果你同時(shí)從同一客戶插入很多行,使用多個(gè)值表的<code>INSERT</code>語句。這比使用分開<code>INSERT</code>語句快(在一些情況中幾倍)。</li>
<li>如果你從不同客戶插入很多行,你能通過使用<code>INSERT DELAYED</code>語句得到更高的速度。見<a HREF="manual_Reference.html#INSERT">7.14<code> INSERT</code>句法</a>。 </li>
<li>注意,用<code>MyISAM</code>,如果在表中沒有刪除的行,能在<code>SELECT</code>:s正在運(yùn)行的同時(shí)插入行。
</li>
<li>當(dāng)從一個(gè)文本文件裝載一個(gè)表時(shí),使用<code>LOAD DATA INFILE</code>。這通常比使用很多<code>INSERT</code>語句快20倍。見<a HREF="manual_Reference.html#LOAD_DATA">7.16<code> LOAD DATA INFILE</code>句法</a>。 </li>
<li>當(dāng)表有很多索引時(shí),有可能多做些工作使得<code>LOAD DATA INFILE</code>更快些。使用下列過程:
<ol>
<li>有選擇地用<code>CREATE TABLE</code>創(chuàng)建表。例如使用<code>mysql</code>或Perl-DBI。
</li>
<li>執(zhí)行<code>FLUSH TABLES</code>,或外殼命令<code>mysqladmin flush-tables</code>。
</li>
<li>使用<code>myisamchk --keys-used=0 -rq /path/to/db/tbl_name</code>。這將從表中刪除所有索引的使用。
</li>
<li>用<code>LOAD DATA INFILE</code>把數(shù)據(jù)插入到表中,這將不更新任何索引,因此很快。</li>
<li>如果你有<code>myisampack</code>并且想要壓縮表,在它上面運(yùn)行<code>myisampack</code>。見<a HREF="manual_Performance.html#Compressed_format">10.6.3 壓縮表的特征</a>。 </li>
<li>用<code>myisamchk -r -q /path/to/db/tbl_name</code>再創(chuàng)建索引。這將在將它寫入磁盤前在內(nèi)存中創(chuàng)建索引樹,并且它更快,因?yàn)楸苊獯罅看疟P尋道。結(jié)果索引樹也被完美地平衡。
</li>
<li>執(zhí)行<code>FLUSH TABLES</code>,或外殼命令<code>mysqladmin flush-tables</code>。</li>
</ol>
<p>這個(gè)過程將被構(gòu)造進(jìn)在MySQL的某個(gè)未來版本的<code>LOAD DATA INFILE</code>。</p>
</li>
<li>你可以鎖定你的表以加速插入。<pre>mysql> LOCK TABLES a WRITE;
mysql> INSERT INTO a VALUES (1,23),(2,34),(4,33);
mysql> INSERT INTO a VALUES (8,26),(6,29);
mysql> UNLOCK TABLES;
</pre>
<p>主要的速度差別是索引緩沖區(qū)僅被清洗到磁盤上一次,在所有<code>INSERT</code>語句完成后。一般有與有不同的<code>INSERT</code>語句那樣奪的索引緩沖區(qū)清洗。如果你能用一個(gè)單個(gè)語句插入所有的行,鎖定就不需要。鎖定也將降低多連接測試的整體時(shí)間,但是對某些線程最大等待時(shí)間將上升(因?yàn)樗麄兊却i)。例如:</p>
<pre>thread 1 does 1000 inserts
thread 2, 3, and 4 does 1 insert
thread 5 does 1000 inserts
</pre>
<p>如果你不使用鎖定,2、3和4將在1和5前完成。如果你使用鎖定,2、3和4將可能不在1或5前完成,但是整體時(shí)間應(yīng)該快大約40%。因?yàn)?lt;code>INSERT</code>,
<code>UPDATE</code>和<code>DELETE</code>操作在<strong>MySQL</strong>中是很快的,通過為多于大約5次連續(xù)不斷地插入或更新一行的東西加鎖,你將獲得更好的整體性能。如果你做很多一行的插入,你可以做一個(gè)<code>LOCK
TABLES</code>,偶爾隨后做一個(gè)<code>UNLOCK TABLES</code>(大約每1000行)以允許另外的線程存取表。這仍然將導(dǎo)致獲得好的性能。當(dāng)然,<code>LOAD
DATA INFILE</code>對裝載數(shù)據(jù)仍然是更快的。 </p>
</li>
</ul>
<p>為了對<code>LOAD DATA INFILE</code>和<code>INSERT</code>得到一些更快的速度,擴(kuò)大關(guān)鍵字緩沖區(qū)。見<a HREF="manual_Performance.html#Server_parameters">10.2.3 調(diào)節(jié)服務(wù)器參數(shù)</a>。</p>
<h3><a NAME="Update_speed" HREF="manual_toc.html#Update_speed">10.5.7 <code>UPDATE</code>查詢的速度</a></h3>
<p>更改查詢被優(yōu)化為有一個(gè)寫開銷的一個(gè)<code>SELECT</code>查詢。寫速度依賴于被更新數(shù)據(jù)大小和被更新索引的數(shù)量。
</p>
<p>使更改更快的另一個(gè)方法是推遲更改并且然后一行一行地做很多更改。如果你鎖定表,做一行一行地很多更改比一次做一個(gè)快。
</p>
<p>注意,動(dòng)態(tài)記錄格式的更改一個(gè)較長總長的記錄,可能切開記錄。因此如果你經(jīng)常這樣做,時(shí)不時(shí)地<code>OPTIMIZE
TABLE</code>是非常重要的。見<a HREF="manual_Reference.html#OPTIMIZE_TABLE">7.9<code>
OPTIMIZE TABLE</code>句法</a>。 </p>
<h3><a NAME="Delete_speed" HREF="manual_toc.html#Delete_speed">10.5.8 <code>DELETE</code>查詢的速度</a></h3>
<p>刪除一個(gè)記錄的時(shí)間精確地與索引數(shù)量成正比。為了更快速地刪除記錄,你可以增加索引緩存的大小。見<a HREF="manual_Performance.html#Server_parameters">10.2.3 調(diào)節(jié)服務(wù)器參數(shù)</a>。 </p>
<p>從一個(gè)表刪除所有行比刪除行的一大部分也要得多。 </p>
<p><a NAME="IDX635"></a> <a NAME="IDX636"></a> </p>
<h2><a NAME="Choosing_table_type" HREF="manual_toc.html#Choosing_table_type">10.6
選擇一種表類型</a></h2>
<p>用MySQL,當(dāng)前(版本 3.23.5)你能從一個(gè)速度觀點(diǎn)在4可用表的格式之間選擇。
<dl COMPACT="Choosing_table_type">
<dt><strong>靜態(tài)MyISAM</strong> </dt>
<dd>這種格式是最簡單且最安全的格式,它也是在磁盤格式最快的。速度來自于數(shù)據(jù)能在磁盤上被找到的難易方式。當(dāng)所定有一個(gè)索引和靜態(tài)格式的東西時(shí),它很簡單,只是行長度乘以行數(shù)量。而且在掃描一張表時(shí),用每次磁盤讀取來讀入常數(shù)個(gè)記錄是很容易的。安全性來自于如果當(dāng)寫入一個(gè)靜態(tài)MyISAM文件時(shí),你的計(jì)算機(jī)崩潰,<code>myisamchk</code>能很容易指出每行在哪兒開始和結(jié)束,因此它通常能回收所有記錄,除了部分被寫入的那個(gè)。注意,在MySQL中,所有索引總能被重建。</dd>
<dt><strong>動(dòng)態(tài)MyISAM</strong> </dt>
<dd>這種格式有點(diǎn)復(fù)雜,因?yàn)槊恳恍斜仨氂幸粋€(gè)頭說明它有多長。當(dāng)一個(gè)記錄在更改時(shí)變長時(shí),它也可以在多于一個(gè)位置上結(jié)束。你能使用<code>OPTIMIZE
table</code>或<code>myisamchk</code>整理一張表。如果你在同一個(gè)表中有象某些<code>VARCHAR</code>或<code>BLOB</code>列那樣存取/改變的靜態(tài)數(shù)據(jù),將動(dòng)態(tài)列移入另外一個(gè)表以避免碎片可能是一個(gè)好主意。
</dd>
<dt><strong>壓縮MyISAM</strong> </dt>
<dd>這是一個(gè)只讀類型,用可選的<code>myisampack</code>工具生成。 </dd>
<dt><strong>內(nèi)存(HEAP 堆)</strong> </dt>
<dd>這種表格式對小型/中型查找表十分有用。對拷貝/創(chuàng)建一個(gè)常用的查找表(用聯(lián)結(jié))到一個(gè)(也許臨時(shí))HEAP表有可能加快多個(gè)表聯(lián)結(jié)。假定我們想要做下列聯(lián)結(jié),用同樣數(shù)據(jù)可能要幾倍時(shí)間。
<pre>SELECT tab1.a, tab3.a FROM tab1, tab2, tab3
WHERE tab1.a = tab2.a and tab2.a = tab3.a and tab2.c != 0;
</pre>
<p>為了加速它,我們可用tab2和tab3的聯(lián)結(jié)創(chuàng)建一張臨時(shí)表,因?yàn)橛孟嗤?
tab1.a )查找。這里是創(chuàng)建該表和結(jié)果選擇的命令。 </p>
<pre>CREATE TEMPORARY TABLE test TYPE=HEAP
SELECT
tab2.a as a2, tab3.a as a3
FROM
tab2, tab3
WHERE
tab2.a = tab3.a and c = 0;
SELECT tab1.a, test.a3 from tab1, test where tab1.a = test.a1;
SELECT tab1.b, test.a3 from tab1, test where tab1.a = test.a1 and something;
</pr
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -