7.2.9 MySQL 如何優(yōu)化 ORDER BY
在一些情況下,MySQL可以直接使用索引來滿足一個 ORDER BY
或 GROUP BY
子句而無需做額外的排序。
盡管 ORDER BY
不是和索引的順序準(zhǔn)確匹配,索引還是可以被用到,只要不用的索引部分和所有的額外的 ORDER BY
字段在 WHERE
子句中都被包括了。下列的幾個查詢都會使用索引來解決 ORDER BY
或 GROUP BY
部分:
SELECT * FROM t1 ORDER BY key_part1,key_part2,... ; SELECT * FROM t1 WHERE key_part1=constant ORDER BY key_part2; SELECT * FROM t1 WHERE key_part1=constant GROUP BY key_part2; SELECT * FROM t1 ORDER BY key_part1 DESC, key_part2 DESC; SELECT * FROM t1 WHERE key_part1=1 ORDER BY key_part1 DESC, key_part2 DESC;
在另一些情況下,MySQL無法使用索引來滿足 ORDER BY
,盡管它會使用索引來找到記錄來匹配 WHERE
子句。這些情況如下:
- 對不同的索引鍵做
ORDER BY
:SELECT * FROM t1 ORDER BY key1, key2;
- 在非連續(xù)的索引鍵部分上做
ORDER BY
:SELECT * FROM t1 WHERE key2=constant ORDER BY key_part2;
- 同時使用了
ASC
和DESC
:SELECT * FROM t1 ORDER BY key_part1 DESC, key_part2 ASC;
- 用于搜索記錄的索引鍵和做
ORDER BY
的不是同一個:SELECT * FROM t1 WHERE key2=constant ORDER BY key1;
- 有很多表一起做連接,而且讀取的記錄中在
ORDER BY
中的字段都不全是來自第一個非常數(shù)的表中(也就是說,在EXPLAIN
分析的結(jié)果中的第一個表的連接類型不是const
)。 - 使用了不同的
ORDER BY
和GROUP BY
表達(dá)式。 - 表索引中的記錄不是按序存儲。例如,
HASH
和HEAP
表就是這樣。
通過執(zhí)行 EXPLAIN SELECT ... ORDER BY
,就知道MySQL是否在查詢中使用了索引。如果 Extra
字段的值是 Using filesort
,則說明MySQL無法使用索引。詳情請看"7.2.1 EXPLAIN
Syntax (Get Information About a SELECT
)"。
當(dāng)必須對結(jié)果進(jìn)行排序時,MySQL 4.1 以前它使用了以下 filesort
算法:
- 根據(jù)索引鍵讀取記錄,或者掃描數(shù)據(jù)表。那些無法匹配
WHERE
分句的記錄都會被略過。 - 在緩沖中每條記錄都用一個‘對’存儲了2個值(索引鍵及記錄指針)。緩沖的大小依據(jù)系統(tǒng)變量
sort_buffer_size
的值而定。 - 當(dāng)緩沖慢了時,就運行 qsort(快速排序)并將結(jié)果存儲在臨時文件中。將存儲的塊指針保存起來(如果所有的‘對’值都能保存在緩沖中,就無需創(chuàng)建臨時文件了)。
- 執(zhí)行上面的操作,直到所有的記錄都讀取出來了。
- 做一次多重合并,將多達(dá)
MERGEBUFF
(7)個區(qū)域的塊保存在另一個臨時文件中。重復(fù)這個操作,直到所有在第一個文件的塊都放到第二個文件了。 - 重復(fù)以上操作,直到剩余的塊數(shù)量小于
MERGEBUFF2
(15)。 - 在最后一次多重合并時,只有記錄的指針(排序索引鍵的最后部分)寫到結(jié)果文件中去。
- 通過讀取結(jié)果文件中的記錄指針來按序讀取記錄。想要優(yōu)化這個操作,MySQL將記錄指針讀取放到一個大的塊里,并且使用它來按序讀取記錄,將記錄放到緩沖中。緩沖的大小由系統(tǒng)變量
read_rnd_buffer_size
的值而定。這個步驟的代碼在源文件 `sql/records.cc' 中。
這個逼近算法的一個問題是,數(shù)據(jù)庫讀取了2次記錄:一次是估算 WHERE
分句時,第二次是排序時。盡管第一次都成功讀取記錄了(例如,做了一次全表掃描),第二次是隨機的讀?。ㄋ饕I已經(jīng)排好序了,但是記錄并沒有)。
在MySQL 4.1 及更新版本中,filesort
優(yōu)化算法用于記錄中不只包括索引鍵值和記錄的位置,還包括查詢中要求的字段。這么做避免了需要2次讀取記錄。改進(jìn)的 filesort
算法做法大致如下:
- 跟以前一樣,讀取匹配
WHERE
分句的記錄。 - 相對于每個記錄,都記錄了一個對應(yīng)的;‘元組’信息信息,包括索引鍵值、記錄位置、以及查詢中所需要的所有字段。
- 根據(jù)索引鍵對‘元組’信息進(jìn)行排序。
- 按序讀取記錄,不過是從已經(jīng)排序過的‘元組’列表中讀取記錄,而非從數(shù)據(jù)表中再讀取一次。
使用改進(jìn)后的 filesort
算法相比原來的,‘元組’比‘對’需要占用更長的空間,它們很少正好適合放在排序緩沖中(緩沖的大小是由 sort_buffer_size
的值決定的)。因此,這就可能需要有更多的I/O操作,導(dǎo)致改進(jìn)的算法更慢。為了避免使之變慢,這種優(yōu)化方法只用于排序‘元組’中額外的字段的大小總和超過系統(tǒng)變量 max_length_for_sort_data
的情況(這個變量的值設(shè)置太高的一個表象就是高磁盤負(fù)載低CPU負(fù)載)。
想要提高 ORDER BY
的速度,首先要看MySQL能否使用索引而非額外的排序過程。如果不能使用索引,可以試著遵循以下策略:
- 增加
sort_buffer_size
的值。 - 增加
read_rnd_buffer_size
的值。 - 修改
tmpdir
,讓它指向一個有很多剩余空間的專用文件系統(tǒng)。如果使用MySQL 4.1或更新,這個選項允許有多個路徑用循環(huán)的格式。各個路徑之間在 Unix 上用冒號(':')分隔開來,在 Windows,NetWare以及OS/2 上用分號(';')。可以利用這個特性將負(fù)載平均分?jǐn)偨o幾個目錄。注意:這些路徑必須是分布在不同物理磁盤上的目錄,而非在同一個物理磁盤上的不同目錄。
默認(rèn)情況下,MySQL也會對所有的 GROUP BY col1, col2, ...
查詢做排序,跟 ORDER BY col1, col2, ...
查詢一樣。如果顯式地包含一個有同樣字段列表的 ORDER BY
分句,MySQL優(yōu)化它的時候并不會損失速度,因為排序總是會發(fā)生。如果一個查詢中包括 GROUP BY
,但是想要避免對結(jié)果排序的開銷,可以通過使用 ORDER BY NULL
來取消排序。例如:
INSERT INTO foo SELECT a, COUNT(*) FROM bar GROUP BY a ORDER BY NULL;
7.2.10 MySQL 如何優(yōu)化 LIMIT
在一些情況下,MySQL在碰到一個使用 LIMIT row_count
但沒使用 HAVING
的查詢時會做不同的處理:
- 如果只是用
LIMIT
來取得很少的一些記錄, MySQL 有時會使用索引,但是更通常的情況是做一個全表掃描。 - 如果
LIMIT row_count
和ORDER BY
一起使用,則MySQL在找到 row_count 條記錄后就會停止排序了,而非對整個表進(jìn)行排序。 - 當(dāng)
LIMIT row_count
和DISTINCT
一起聯(lián)合起來時,MySQL在找到 row_count 條唯一記錄后就不再搜索了。 - 在某些情況下,
GROUP BY
可以通過按照順序讀取索引鍵來實現(xiàn)(或者在索引鍵上做排序)并且計算累計信息直到索引鍵改變了。在這種情況下,LIMIT row_count
不會計算任何非必須的GROUP BY
值。 - 一旦MySQL將請求的記錄全數(shù)發(fā)送給客戶端后,它就中止查詢除非使用了
SQL_CALC_FOUND_ROWS
。 LIMIT 0
總是返回一個空的結(jié)果集。這對于檢查查詢或者取得結(jié)果字段的類型非常有用。- 當(dāng)服務(wù)器使用臨時表來處理查詢,則
LIMIT row_count
可以用來計算需要多少空間。
7.2.11 如何避免全表掃描
如果MySQL需要做一次全表掃描來處理查詢時,在 EXPLAIN
的結(jié)果中 type
字段的值是 ALL
。在以下幾種條件下,MySQL就會做全表掃描:
- 數(shù)據(jù)表是在太小了,做一次全表掃描比做索引鍵的查找來得快多了。當(dāng)表的記錄總數(shù)小于10且記錄長度比較短時通常這么做。
- 沒有合適用于
ON
或WHERE
分句的索引字段。 - 讓索引字段和常量值比較,MySQL已經(jīng)計算(基于索引樹)到常量覆蓋了數(shù)據(jù)表的很大部分,因此做全表掃描應(yīng)該會來得更快。詳情請看"7.2.4 How MySQL Optimizes
WHERE
Clauses"。 - 通過其他字段使用了一個基數(shù)很小(很多記錄匹配索引鍵值)的索引鍵。這種情況下,MySQL認(rèn)為使用索引鍵需要大量查找,還不如全表掃描來得更快。
對于小表來說,全表掃描通常更合適。但是對大表來說,嘗試使用以下技術(shù)來避免讓優(yōu)化程序錯誤地選擇全表掃描:
- 執(zhí)行
ANALYZE TABLE tbl_name
更新要掃描的表的索引鍵分布。詳情請看"14.5.2.1ANALYZE TABLE
Syntax"。 - 使用
FORCE INDEX
告訴MySQL,做全表掃描的話會比利用給定的索引更浪費資源。詳情請看"14.1.7SELECT
Syntax"。SELECT * FROM t1, t2 FORCE INDEX (index_for_column) WHERE t1.col_name=t2.col_name;
- 啟動
mysqld
時使用參數(shù)--max-seeks-for-key=1000
或者執(zhí)行SET max_seeks_for_key=1000
來告訴優(yōu)化程序,所有的索引都不會導(dǎo)致超過1000次的索引搜索。請查看章節(jié)"5.2.3 Server System Variables"。
7.2.12 加速 INSERT
插入一條記錄花費的時間由以下幾個因素決定,后面的數(shù)字大致表示影響的比例:
- 連接:(3)
- 發(fā)送查詢給服務(wù)器:(2)
- 解析查詢:(2)
- 插入記錄:(1 x 記錄大?。?
- 插入索引:(1 x 索引數(shù)量)
- 關(guān)閉:(1)
這里并沒有考慮初始化時打開數(shù)據(jù)表的開銷,因為每次運行查詢只會做這么一次。
如果是 B-tree 索引的話,隨著索引數(shù)量的增加,插入記錄的速度以 log N 的比例下降。
可以使用以下幾種方法來提高插入速度:
- 如果要在同一個客戶端在同一時間內(nèi)插入很多記錄,可以使用
INSERT
語句附帶有多個VALUES
值。這種做法比使用單一值的INSERT
語句快多了(在一些情況下比較快)。如果是往一個非空的數(shù)據(jù)表里增加記錄,可以調(diào)整變量bulk_insert_buffer_size
的值使之更快。詳情請看"5.2.3 Server System Variables"。 - 如果要從不同的客戶端中插入大量記錄,使用
INSERT DELAYED
語句也可以提高速度。詳情請看"14.1.4INSERT
Syntax"。 - 對
MyISAM
而言,可以在SELECT
語句正在運行時插入記錄,只要這時候沒有正在刪除記錄。 - 想要將一個文本文件加載到數(shù)據(jù)表中,可以使用
LOAD DATA INFILE
。這通常是使用大量INSERT
語句的20倍。詳情請看"14.1.5LOAD DATA INFILE
Syntax"。 - 通過一些額外的工作,就可能讓
LOAD DATA INFILE
在數(shù)據(jù)表有大量索引的情況下運行的更快。步驟如下:
- 用
CREATE TABLE
隨便創(chuàng)建一個表。 - 執(zhí)行
FLUSH TABLES
語句或mysqladmin flush-tables
命令。 - 執(zhí)行
myisamchk --keys-used=0 -rq /path/to/db/tbl_name
命令,刪掉數(shù)據(jù)表的所有索引。 - 執(zhí)行
LOAD DATA INFILE
,數(shù)據(jù)插入到表中,由于無需更新表索引,因此這將非??臁? - 如果將來只是讀取改表,運行
myisampack
讓數(shù)據(jù)表變得更小點。詳情查看"15.1.3.3 Compressed Table Characteristics"。 - 運行
myisamchk -r -q /path/to/db/tbl_name
重建索引。創(chuàng)建的索引樹在寫入磁盤前先保存在內(nèi)存中,這省去了磁盤搜索,因此速度快多了。重建后的索引樹分布非常均衡。 - 執(zhí)行
FLUSH TABLES
語句或mysqladmin flush-tables
命令。
注意,LOAD DATA INFILE
將數(shù)據(jù)插入一個空表時,也會做前接優(yōu)化;主要的不同在于:運行myisamchk
會分配更多的臨時內(nèi)存用于創(chuàng)建索引,而執(zhí)行LOAD DATA INFILE
命令則是讓數(shù)據(jù)庫服務(wù)器分配內(nèi)存用于重建索引。從 MySQL 4.0 起,可以運行ALTER TABLE tbl_name DISABLE KEYS
來代替myisamchk --keys-used=0 -rq /path/to/db/tbl_name
,運行ALTER TABLE tbl_name ENABLE KEYS
代替myisamchk -r -q /path/to/db/tbl_name
。這么做就可以省去FLUSH TABLES
步驟。 - 用
- 可以在鎖表后,一起執(zhí)行幾個語句來加速
INSERT
操作:LOCK TABLES a WRITE; INSERT INTO a VALUES (1,23),(2,34),(4,33); INSERT INTO a VALUES (8,26),(6,29); UNLOCK TABLES;
這對性能提高的好處在于:直到所有的
INSERT
語句都完成之后,索引緩存一次性刷新到磁盤中。通常情況是,多有少次INSERT
語句就會有多數(shù)次索引緩存刷新到磁盤中的開銷。如果能在一個語句中一次性插入多個值的話,顯示的鎖表操作也就沒必要了。對事務(wù)表而言,用BEGIN/COMMIT
代替LOCK TABLES
來提高速度。鎖表也回降低多次連接測試的總時間,盡管每個獨立連接為了等待鎖的最大等待時間也會增加。例如:Connection 1 does 1000 inserts Connections 2, 3, and 4 do 1 insert Connection 5 does 1000 inserts
如果沒有鎖表,則連接2,3,4會在1,5之前就做完了。如果鎖表了,則連接2,3,4可能在1,5之后才能完成,但是總時間可能只需要40%。MySQL的
INSERT
,UPDATE
,DELETE
操作都非常快,不過在一個語句中如果有超過5個插入或者更新時最好加鎖以得到更好的性能。如果要一次性做很多個插入,最好是在每個循環(huán)(大約1000次)的前后加上LOCK TABLES
和UNLOCK TABLES
,從而讓其他進(jìn)程也能訪問數(shù)據(jù)表;這么做性能依然不錯。INSERT
總是比LOAD DATA INFILE
插入數(shù)據(jù)來得慢,因為二者的實現(xiàn)策略有著分明的不同。 - 想要讓
MyISAM
表更快,在LOAD DATA
和
INFILEINSERT
時都可以增加系統(tǒng)變量key_buffer_size
的值,詳情請看"7.5.2 Tuning Server Parameters"。
7.2.13 加速 UPDATE
UPDATE
語句的優(yōu)化和 SELECT
一樣,只不過它多了額外的寫入開銷。寫入的開銷取決于要更新的記錄數(shù)以及索引數(shù)。如果索引沒有發(fā)生變化,則就無需更新。
另一個提高更新速度的辦法是推遲更新并且把很多次更新放在后面一起做。如果鎖表了,那么同時做很多次更新比分別做更新來得快多了。
注意,如果是在 MyISAM
表中使用了動態(tài)的記錄格式,那么記錄被更新為更長之后就可能會被拆分。如果經(jīng)常做這個,那么偶爾做一次 OPTIMIZE TABLE
就顯得非常重要了。詳情請看"14.5.2.5 OPTIMIZE TABLE Syntax"。
7.2.14 加速 DELETE
刪除單個記錄的時間和它的索引個數(shù)幾乎成正比。想更快地刪除記錄,可以增加索引鍵的緩存。詳情請看"7.5.2 Tuning Server Parameters"。
如果想要刪除數(shù)據(jù)表的所有記錄,請使用 TRUNCATE TABLE tbl_name
而不是 DELETE FROM tbl_name
。詳情請看"14.1.9 TRUNCATE Syntax"。
7.2.15 其他優(yōu)化點子
本章節(jié)列出了一些改善查詢處理速度的其他點子:
- 使用永久連接到數(shù)據(jù)庫,避免連接的開銷。如果需要初始化很多連接,而又不能用永久連接,那么可以修改變量
thread_cache_size
的值,詳情請看"7.5.2 Tuning Server Parameters"。 - 總是檢查查詢是否利用了表中已有的索引。在MySQL中,可以用
EXPLAIN
語句來分析。詳情請看"7.2.1 EXPLAIN Syntax (Get Information About a SELECT)"。 - 盡量不要在經(jīng)常需要更新的
MyISAM
表上用太過復(fù)雜的SELECT
語句,這是為了避免在讀和寫之間爭奪鎖。 - 在
MyISAM
表中,如果沒有正在刪除記錄,則可以在其他查詢正在讀取數(shù)據(jù)的同時插入記錄。如果這種情況十分重要,那么就要盡量在表沒有刪除記錄時才使用表。另一個可能的辦法就是在刪除一大堆記錄之后執(zhí)行OPTIMIZE TABLE
語句。 - 如果總是需要按照
expr1, expr2, ...
的順序取得記錄,那么請使用ALTER TABLE ... ORDER BY expr1, expr2, ...
修改表。通過這種方法擴(kuò)充修改表之后,就可能獲得更高的性能表現(xiàn)。 - 在一些情況下,讓一個字段類型是 ``hashed`` ,它基于其他字段信息。如果這個字段比較短而且基本上都是唯一值的話,那么就可能會比在幾個字段上使用一個大索引來得更快,很簡單的就能使用這樣的額外字段,如下:
SELECT * FROM tbl_name WHERE hash_col=MD5(CONCAT(col1,col2)) AND col1='constant' AND col2='constant';
- 如果
MyISAM
表經(jīng)常大量修改,那么要盡量避免修改所有的變長字段(VARCHAR, BLOB,TEXT
)。盡管表中只有一個變長字段,它也會采用動態(tài)記錄格式的。詳情請看"15 MySQL Storage Engines and Table Types"。 - 通常情況下,當(dāng)數(shù)據(jù)表記錄變 ``大`` 之后,將表拆分成幾個不同的表并沒有多大用處。訪問一條記錄是最大的性能點在于磁盤搜索時找到記錄的第一個字節(jié)上。只要找到記錄的位置后,現(xiàn)在的大部分磁盤對于大部分的應(yīng)用程序來說都能很快的讀取到記錄。將
MyISAM
表拆分成多個唯一有關(guān)系的情況是,數(shù)據(jù)表中動態(tài)格式的字段(見上)就可以被修改成固定大小的記錄,或者需要頻繁的掃描表,但是卻不需要讀取出大部分的字段。詳情請看"15 MySQL Storage Engines and Table Types"。 - 如果需要頻繁的對一個表做基于很多字段信息的統(tǒng)計信息的話,那么可能新建一個表來存儲這些實時更新的統(tǒng)計結(jié)果會更好。類似下面的更新就會非常快了:
UPDATE tbl_name SET count_col=count_col+1 WHERE key_col=constant;
如果只需要表級鎖(多個讀/一個寫),那么采用
MyISAM
存儲引擎就非常重要了,例如MyISAM
和ISAM
表。這在很多的數(shù)據(jù)庫中也會有不錯的性能表現(xiàn),因為行級鎖管理程序在這種情況下也基本上沒什么用。 - 如果需要從很大的日志表中搜集統(tǒng)計信息的話,可以用摘要表來代替掃描整個日志表。維護(hù)摘要表比保持 ``實時`` 的統(tǒng)計信息來得更快。當(dāng)事情發(fā)生變化時(比如商業(yè)決策),重新建里摘要表比修改運營中的應(yīng)用程序快多了。
- 如果可能,最好是分類報告 ``實時`` 還是 ``統(tǒng)計`` 的,報告所需要的數(shù)據(jù)只需要來自摘要表,摘要表的信息則是周期的從實時數(shù)據(jù)中產(chǎn)生。
- 應(yīng)該認(rèn)識到一個優(yōu)點就是字段有默認(rèn)值。當(dāng)要插入的值和默認(rèn)值不一致時才需要明確指定。這就省去了MySQL需要來提高插入速度這步了。
- 在一些情況下,將數(shù)據(jù)組裝存儲在
BLOB
類型字段中更方便。那么在應(yīng)用程序中就需要增加額外的命令來組裝和拆開BLOB
字段中的值,不過這么做在一些時候就可以節(jié)省很多存儲開銷。這在數(shù)據(jù)無需遵從記錄-和-字段
格式的表結(jié)構(gòu)是很實用。 - 通常地,應(yīng)該保存所有的冗余數(shù)據(jù)(在數(shù)據(jù)庫原理中叫做"第三范式")。然而,為了能取得更高的效率復(fù)制一些信息或者創(chuàng)建摘要表也是劃算的。
- 存儲過程或者
UDFs
(用戶定義函數(shù)) 的方式在執(zhí)行一些任務(wù)時可能性能更高。盡管如此,當(dāng)數(shù)據(jù)庫不支持這些特性時,還是有其他的替代方法可以達(dá)到目的,即使它們有點慢。 - 可以從查詢緩存或應(yīng)答中取得結(jié)果,然后將很多次的插入及更新操作放在一起做。如果數(shù)據(jù)庫支持表鎖(如MySQL和ORACLE),那么這就可以確保索引緩存在所有的更新操作之后只需要刷新一次。
- 當(dāng)不需要直到數(shù)據(jù)什么時候?qū)懭氡碇袝r,可以用
INSERT DELAYED
。這就會提高速度,因為多條記錄同時在一起做一次磁盤寫入操作。
- 當(dāng)想讓
SELECT
語句的優(yōu)先級比插入操作還高時,用INSERT LOW_PRIORITY
。
- 用
SELECT HIGH_PRIORITY
來使檢索記錄跳過隊列,也就是說即使有其他客戶端正要寫入數(shù)據(jù),也會先讓SELECT
執(zhí)行完。
- 在一條
INSERT
語句中采用多重記錄插入格式(很多數(shù)據(jù)庫都支持)。
- 用
LOAD DATA INFILE
來導(dǎo)入大量數(shù)據(jù),這比INSERT
快。
- 用
AUTO_INCREMENT
字段來生成唯一值。
- 定期執(zhí)行
OPTIMIZE TABLE
防止使用動態(tài)記錄格式的MyISAM
表產(chǎn)生碎片。詳情請看"15.1.3MyISAM
Table Storage Formats"。
- 采用
HEAP
表,它可能會提高速度。詳情請看"15.1.3MyISAM
Table Storage Formats"。
- 正常的WEB服務(wù)器配置中,圖片文件最好以文件方式存儲,只在數(shù)據(jù)庫中保存文件的索引信息。這么做的原因是,通常情況下WEB服務(wù)器對于文件的緩存總是做的比數(shù)據(jù)庫來得好,因此使用文件存儲會讓系統(tǒng)更容易變得更快。
- 對于頻繁訪問的不是很重要的數(shù)據(jù),可以保存在內(nèi)存表中,例如對那些web客戶端不能保存cookies時用于保存最后一次顯示的標(biāo)題等信息。
- 在不同表中值相同的字段應(yīng)該將它們聲明為一樣的類型。在 MySQL 3.23 之前,不這么做的話在表連接時就會比較慢。讓字段名盡可能簡單,例如,在一個叫做
customer
的表中,用name
來代替customer_name
作為字段名。為了讓字段名在其他數(shù)據(jù)庫系統(tǒng)中也能移植,應(yīng)該保持在18個字符長度以內(nèi)。
- 如果需要真正的高速,建議看看各種數(shù)據(jù)庫服務(wù)器支持的底層數(shù)據(jù)存儲接口之間的區(qū)別。例如,通過直接訪問MySQL的
MyISAM
存儲引擎,會比通過其他的SQL接口快2-5倍。這要求數(shù)據(jù)必須和應(yīng)用程序在同一個服務(wù)器上,并且它通常只被一個進(jìn)程訪問(因為外部文件鎖確實慢)。只用一個進(jìn)程就可以消除在MySQL服務(wù)器上引入底層的MyISAM
指令引發(fā)的問題了(這容易獲得更高性能,如果需要的話)。由于數(shù)據(jù)庫接口設(shè)計的比較細(xì)心,就很容易支持這種優(yōu)化方式了。
- 如果使用數(shù)字型數(shù)據(jù)的話,在很多情況下想要訪問數(shù)據(jù)庫(使用在線連接)的信息會比采用文本文件來得快。由于數(shù)字型信息相比文本文件在數(shù)據(jù)庫中存儲的更加緊湊,因此訪問時只需要更少的磁盤搜索。而且在應(yīng)用程序中也可以節(jié)省代碼,因為無需解析文本文件以找到對應(yīng)的行和字段。
- 數(shù)據(jù)庫復(fù)制對一些操作會有性能上的益處。可以將客戶端從多個復(fù)制服務(wù)器上取得數(shù)據(jù),這就能將負(fù)載分?jǐn)偭?。為了避免備份?shù)據(jù)時會讓主服務(wù)器變慢,還可以將備份放在從服務(wù)器上。詳情請看"6 Replication in MySQL"。
- 定義
MyISAM
表時增加選項DELAY_KEY_WRITE=1
,這樣的話就會另索引更新更快,因為只有等到數(shù)據(jù)表關(guān)閉了才會刷新磁盤。不過缺點是可能會在數(shù)據(jù)表還打開時服務(wù)器被殺死,可以使用參數(shù)--myisam-recover
來保證數(shù)據(jù)的安全,或者在數(shù)據(jù)庫重啟前運行myisamchk
命令(盡管如此,在這種情況下,使用DELAY_KEY_WRITE
的話也不會丟失任何東西,因為索引總是可以從數(shù)據(jù)中重新生成)。