轉帖: 轉一篇非常好的MySQL優化的文章
MySQL的優化
作者:晏子 (2001-05-14 12:20:05)
一、我們可以且應該優化什 麼?
硬體
作業系統/軟體庫
SQL伺服器(設定和查詢)
應用程式設計介面(API)
應用程式
--------------------------------------------------------------------------------
二、優化硬體
如果你需要龐大的資料庫表(>2G),你應該考慮使用64位的硬體結構,像Alpha、 Sparc或即將推出的IA64。因為MySQL內部使用大量64位的整數,64位的CPU將提供更好的效能。
對大資料庫,優化的次序 一般是RAM、快速硬碟、CPU能力。
更多的記憶體通過將最常用的鍵碼頁面存放在記憶體中可以加速鍵碼的更新。
如果不使 用事務安全(transaction-safe)的表或有大表並且想避免長檔案檢查,一臺UPS就能夠在電源故障時讓系統安全關閉。
對 於資料庫存放在一個專用伺服器的系統,應該考慮1G的乙太網。延遲與吞吐量同樣重要。
--------------------------------------------------------------------------------
三、優化磁碟
為系統、程式和臨時檔案配備一個專用磁碟,如果確是進行很多修改工作,將更新日誌和事務日誌放在專用磁 盤上。
低 尋道時間對資料庫磁碟非常重要。對與大表,你可以估計你將需要log(行數)/log(索引塊長度/3*2/(鍵碼長度 + 資料指標長度))+1次尋到才能找到一行。對於有500000行的表,索引Mediun int型別的列,需要log(500000) / log(1024/3*2/(3 + 2))+1=4次尋道。上述索引需要500000*7*3/2=5.2M的空間。實際上,大多數塊將被快取,所以大概只需要1-2次尋道。
然而 對於寫入(如上),你將需要4次尋道請求來找到在哪裡存放新鍵碼,而且一般要2次尋道來更新索引並寫入一行。
對於非常大的資料庫,你的應用將受 到磁碟尋道速度的限制,隨著資料量的增加呈N log N資料級遞增。
將資料庫和表分在不同的磁碟上。在MySQL中,你可以為此而使用符號鏈 接。
條列磁碟(RAID 0)將提高讀和寫的吞吐量。
帶映象的條列(RAID 0+1)將更安全並提高讀取的吞吐量。寫入的吞吐量將有所降低。
不要對臨時檔案或可以很容易地重建的資料所在的磁碟使用映象或RAID(除了 RAID 0)。
在Linux上,在引導時對磁碟使用命令hdparm -m16 -d1以啟用同時讀寫多個扇區和DMA功能。這可以將響應時間提高5~50%。
在Linux上,用async (預設)和noatime掛載磁碟(mount)。
對於某些特定應用,可以對某些特定表使用記憶體磁碟,但通常不需要。
--------------------------------------------------------------------------------
四、優化作業系統
不要交換區。如果記憶體不足,增加更多的記憶體或配置你的系統使用較少記憶體。
不要使用NFS 磁碟(會有NFS鎖定的問題)。
增加系統和MySQL伺服器的開啟檔案數量。(在safe_mysqld指令碼中加入ulimit -n #)。
增加系統的程式和執行緒數量。
如果你有相對較少的大表,告訴檔案系統不要將檔案打碎在不同的磁軌上(Solaris)。
使用 支援大檔案的檔案系統(Solaris)。
選擇使用哪種檔案系統。在Linux上的Reiserfs對於開啟、讀寫都非常快。檔案檢查只需幾秒 種。
--------------------------------------------------------------------------------
五、選擇應用程式設計介面
PERL
可在不同的作業系統和資料庫之間移植。
適宜快速原型。
應 該使用DBI/DBD介面。
PHP
比PERL易學。
使用比PERL少的資源。
通過升級到PHP4可以獲得更快的 速度。
C
MySQL的原生介面。
較快並賦予更多的控制。
低層,所以必須付出更多。
C++
較 高層次,給你更多的時間來編寫應用。
仍在開發中
ODBC
執行在Windows和Unix上。
幾乎可在不同的 SQL伺服器間移植。
較慢。MyODBC只是簡單的直通驅動程式,比用原生介面慢19%。
有很多方法做同樣的事。很難像很多ODBC 驅動程式那樣執行,在不同的領域還有不同的錯誤。
問題成堆。Microsoft偶爾還會改變介面。
不明朗的未 來。(Microsoft更推崇OLE而非ODBC)
ODBC
執行在Windows和Unix上。
幾乎可在不同的SQL服 務器間移植。
較慢。MyODBC只是簡單的直通驅動程式,比用原生介面慢19%。
有很多方法做同樣的事。很難像很多ODBC驅動程式 那樣執行,在不同的領域還有不同的錯誤。
問題成堆。Microsoft偶爾還會改變介面。
不明朗的未來。(Microsoft更推崇 OLE而非ODBC)
JDBC
理論上可在不同的作業系統何時據庫間移植。
可以執行在web客戶端。
Python 和其他
可能不錯,可我們不用它們。
--------------------------------------------------------------------------------
六、優化應用
應該集中精力解決問題。
在編寫應用時,應該決定什麼是最重要的:
速度
操 作系統間的可移植性
SQL伺服器間的可移植性
使用持續的連線。.
快取應用中的資料以減少SQL伺服器的負載。
不 要查詢應用中不需要的列。
不要使用SELECT * FROM table_name...
測試應用的所有部分,但將大部分精力放在 在可能最壞的合理的負載下的測試整體應用。通過以一種模組化的方式進行,你應該能用一個快速“啞模組”替代找到的瓶頸,然後很容易地標出下一個瓶頸。
如 果在一個批處理中進行大量修改,使用LOCK TABLES。例如將多個UPDATES或DELETES集中在一起。
--------------------------------------------------------------------------------
七、應該使用可移植的應用
Perl DBI/DBD
ODBC
JDBC
Python(或 其他有普遍SQL介面的語言)
你應該只使用存在於所有目的SQL伺服器中或可以很容易地用其他構造模擬的SQL構 造。[url]www.mysql.com上的Crash-me頁可以幫助你。[/url]
為作業系統/SQL伺服器編寫包裝程式來提供缺少的 功能。
--------------------------------------------------------------------------------
八、如果你需要更快的速度,你應該:
找出瓶頸(CPU、磁碟、記憶體、SQL伺服器、作業系統、API或應用)並集中 全力解決。
使用給予你更快速度/靈活性的擴充套件。
逐漸瞭解SQL伺服器以便能為你的問題使用可能最快的SQL構造並避免瓶頸。
優 化表佈局和查詢。
使用複製以獲得更快的選擇(select)速度。
如果你有一個慢速的網路連線資料庫,使用壓縮客戶/伺服器協議。
不 要害怕時應用的第一個版本不能完美地移植,在你解決問題時,你總是可以在以後優化它。
--------------------------------------------------------------------------------
九、優化MySQL
挑選編譯器和編譯選項。
位你的系統尋找最好的啟動選項。
通讀MySQL參考 手冊並閱讀Paul DuBios的《MySQL》一書。(已有中文版-譯註)
多用EXPLAIN SELECT、SHOW VARIABLES、SHOW STATUS和SHOW PROCESSLIST。
瞭解查詢優化器的工作原理。
優化表的格式。
維 護你的表(myisamchk、CHECK TABLE、 OPTIMIZE TABLE)
使用MySQL的擴充套件功能以讓一切快速完成。
如 果你注意到了你將在很多場合需要某些函式,編寫MySQL UDF函式。
不要使用表級或列級的GRANT,除非你確實需要。
購買 MySQL技術支援以幫助你解決問題:)
--------------------------------------------------------------------------------
十、編譯和安裝MySQL
通過位你的系統挑選可能最好的編譯器,你通常可以獲得10-30%的效能提高。
在 Linux/Intel平臺上,用pgcc(gcc的奔騰晶片優化版)編譯MySQL。然而,二進位制程式碼將只能執行在Intel奔騰CPU上。
對 於一種特定的平臺,使用MySQL參考手冊上推薦的優化選項。
一般地,對特定CPU的原生編譯器(如Sparc的Sun Workshop)應該比gcc提供更好的效能,但不總是這樣。
用你將使用的字符集編譯MySQL。
靜態編譯生成mysqld的執行 檔案(用--with-mysqld-ldflags=all-static)並用strip sql/mysqld整理最終的執行檔案。
注 意,既然MySQL不使用C++擴充套件,不帶擴充套件支援編譯MySQL將贏得巨大的效能提高。
如果作業系統支援原生執行緒,使用原生執行緒(而不用 mit-pthreads)。
用MySQL基準測試來測試最終的二進位制程式碼。
--------------------------------------------------------------------------------
十一、維護
如果可能,偶爾執行一下OPTIMIZE table,這對大量更新的變長行非常重要。
偶爾用 myisamchk -a更新一下表中的鍵碼分佈統計。記住在做之前關掉MySQL。
如果有碎片檔案,可能值得將所有檔案複製到另一個磁碟上, 清除原來的磁碟並拷迴檔案。
如果遇到問題,用myisamchk或CHECK table檢查表。
用mysqladmin -i10 precesslist extended-status監控MySQL的狀態。
用MySQL GUI客戶程式,你可以在不同的視窗內監控程式列表和狀態。
使用mysqladmin debug獲得有關鎖定和效能的資訊。
--------------------------------------------------------------------------------
十二、優化SQL
揚SQL之長,其它事情交由應用去做。使用SQL伺服器來做:
找出基於 WHERE子句的行。
JOIN表
GROUP BY
ORDER BY
DISTINCT
不要使用SQL來 做:
檢驗資料(如日期)
成為一隻計算器
技巧:
明智地使用鍵碼。
鍵碼適合搜尋,但不適 合索引列的插入/更新。
保持資料為資料庫第三正規化,但不要擔心冗餘資訊或這如果你需要更快的速度,建立總結表。
在大表上不做 GROUP BY,相反建立大表的總結表並查詢它。
UPDATE table set count=count+1 where key_column=constant非常快。
對於大表,或許最好偶爾生成總結表而不是一直保持總結表。
充分利用INSERT的默 認值。
--------------------------------------------------------------------------------
十三、不同SQL伺服器的速度差別(以秒計)
通過鍵碼讀取2000000行: NT Linux
mysql 367 249
mysql_odbc 464
db2_odbc 1206
informix_odbc 121126
ms-sql_odbc 1634
oracle_odbc 20800
solid_odbc 877
sybase_odbc 17614
插入350768行: NT Linux
mysql 381 206
mysql_odbc 619
db2_odbc 3460
informix_odbc 2692
ms-sql_odbc 4012
oracle_odbc 11291
solid_odbc 1801
sybase_odbc 4802
在上述測試中,MySQL配置8M快取記憶體執行,其他資料庫以預設安裝執行。
--------------------------------------------------------------------------------
十四、重要的MySQL啟動選項
back_log 如果需要大量新連線,修改它。
thread_cache_size 如果需要大量新連線,修改它。
key_buffer_size 索引頁池,可以設成很大。
bdb_cache_size BDB表使用的記錄和鍵嗎快取記憶體。
table_cache 如果有很多的表和併發連線,修改它。
delay_key_write 如果需要快取所有鍵碼寫入,設定它。
log_slow_queries 找出需花大量時間的查詢。
max_heap_table_size 用於GROUP BY
sort_buffer 用於ORDER BY和GROUP BY
myisam_sort_buffer_size 用於REPAIR TABLE
join_buffer_size 在進行無鍵嗎的聯結時使用。
--------------------------------------------------------------------------------
十五、優化表
MySQL擁有一套豐富的型別。你應該對每一列嘗試使用最有效的型別。
ANALYSE過程可 以幫助你找到表的最優型別:SELECT * FROM table_name PROCEDURE ANALYSE()。
對於不儲存NULL 值的列使用NOT NULL,這對你想索引的列尤其重要。
將ISAM型別的表改為MyISAM。
如果可能,用固定的表格式建立表。
不 要索引你不想用的東西。
利用MySQL能按一個索引的字首進行查詢的事實。如果你有索引INDEX(a,b),你不需要在a上的索引。
不 在長CHAR/VARCHAR列上建立索引,而只索引列的一個字首以節省儲存空間。CREATE TABLE table_name (hostname CHAR(255) not null, index(hostname(10)))
對每個表使用最有效的表格式。
在不同表中儲存 相同資訊的列應該有同樣的定義並具有相同的列名。
--------------------------------------------------------------------------------
十六、MySQL如何次儲存資料
資料庫以目錄儲存。
表以檔案儲存。
列以變長或定長格式儲存在文 件中。對BDB表,資料以頁面形式儲存。
支援基於記憶體的表。
資料庫和表可在不同的磁碟上用符號連線起來。
在Windows 上,MySQL支援用.sym檔案內部符號連線資料庫。
--------------------------------------------------------------------------------
十七、MySQL表型別
HEAP表:固定行長的表,只儲存在記憶體中並用HASH索引進行索引。
ISAM 表:MySQL 3.22中的早期B-tree表格式。
MyIASM:IASM表的新版本,有如下擴充套件:
二進位制層次的可移植性。
NULL 列索引。
對變長行比ISAM表有更少的碎片。
支援大檔案。
更好的索引壓縮。
更好的鍵嗎統計分佈。
更好 和更快的auto_increment處理。
來自Sleepcat的Berkeley DB(BDB)表:事務安全(有BEGIN WORK/COMMIT|ROLLBACK)。
--------------------------------------------------------------------------------
十八、MySQL行型別(專指IASM/MyIASM表)
如果所有列是定長格式(沒有VARCHAR、BLOB或 TEXT),MySQL將以定長表格式建立表,否則表以動態長度格式建立。
定長格式比動態長度格式快很多並更安全。
動態長度行格式一 般佔用較少的儲存空間,但如果表頻繁更新,會產生碎片。
在某些情況下,不值得將所有VARCHAR、BLOB和TEXT列轉移到另一個表中,只 是獲得主表上的更快速度。
利用myiasmchk(對ISAM,pack_iasm),可以建立只讀壓縮表,這使磁碟使用率最小,但使用慢速磁 盤時,這非常不錯。壓縮表充分地利用將不再更新的日誌表
--------------------------------------------------------------------------------
十九、MySQL快取記憶體(所有執行緒共享,一次性分配)
鍵碼快取:key_buffer_size,預設8M。
表 快取:table_cache,預設64。
執行緒快取:thread_cache_size,預設0。
主機名快取:可在編譯時修改,默 認128。
記憶體對映表:目前僅用於壓縮表。
注意:MySQL沒有行快取記憶體,而讓作業系統處理。
--------------------------------------------------------------------------------
二十、MySQL快取區變數(非共享,按需分配)
sort_buffer:ORDER BY/GROUP BY
record_buffer: 掃描表。
join_buffer_size:無鍵聯結
myisam_sort_buffer_size:REPAIR TABLE
net_buffer_length: 對於讀SQL語句並快取結果。
tmp_table_size:臨時結果的HEAP表大小。
--------------------------------------------------------------------------------
二十一、MySQL表快取記憶體工作原理
每個MyISAM表的開啟例項(instance)使用一個索引檔案和一個數 據檔案。如果表被兩個執行緒使用或在同一條查詢中使用兩次,MyIASM將共享索引檔案而是開啟資料檔案的另一個例項。
如果所有在快取記憶體中的表 都在使用,快取將臨時增加到比表快取尺寸大些。如果是這樣,下一個被釋放的表將被關閉。
你可以通過檢查mysqld的 Opened_tables變數以檢查表快取是否太小。如果該值太高,你應該增大表快取記憶體。
--------------------------------------------------------------------------------
二十二、MySQL擴充套件/優化-提供更快的速度
使用優化的表型別(HEAP、MyIASM或BDB表)。
對 資料使用優化的列。
如果可能使用定長行。
使用不同的鎖定型別(SELECT HIGH_PRIORITY,INSERT LOW_PRIORITY)
Auto_increment
REPLACE (REPLACE INTO table_name VALUES (...))
INSERT DELAYED
LOAD DATA INFILE / LOAD_FILE()
使 用多行INSERT一次插入多行。
SELECT INTO OUTFILE
LEFT JOIN, STRAIGHT JOIN
LEFT JOIN ,結合IS NULL
ORDER BY可在某些情況下使用鍵碼。
如果只查詢在一個索引中的列,將只使用索引樹解決查詢。
聯結一般比子查詢快(對大多數SQL伺服器亦如此)。
LIMIT
SELECT * from table1 WHERE a > 10 LIMIT 10,20
DELETE * from table1 WHERE a > 10 LIMIT 10
foo IN (常數列表) 高度優化。
GET_LOCK()/RELEASE_LOCK()
LOCK TABLES
INSERT 和SELECT可同時執行。
UDF函式可裝載進一個正在執行的伺服器。
壓縮只讀表。
CREATE TEMPORARY TABLE
CREATE TABLE .. SELECT
帶RAID選項的MyIASM表將檔案分割成很多檔案以突破某些檔案系統的 2G限制。
Delay_keys
複製功能
--------------------------------------------------------------------------------
二十二、MySQL何時使用索引
對一個鍵碼使用>, >=, =,
SELECT * FROM table_name WHERE key_part1=1 and key_part2 > 5;
SELECT * FROM table_name WHERE key_part1 IS NULL;
當使用不以萬用字元開始的LIKE
SELECT * FROM table_name WHERE key_part1 LIKE 'jani%'
在進行聯結時從另一個表中提取行時
SELECT * from t1,t2 where t1.col=t2.key_part
找出指定索引的MAX()或MIN()值
SELECT MIN(key_part2),MAX(key_part2) FROM table_name where key_part1=10
一個鍵 碼的字首使用ORDER BY或GROUP BY
SELECT * FROM foo ORDER BY key_part1,key_part2,key_part3
在所有用在查詢中的列是鍵碼的一部分時間
SELECT key_part3 FROM table_name WHERE key_part1=1
--------------------------------------------------------------------------------
二十三、MySQL何時不使用索引
如果MySQL能估計出它將可能比掃描整張表還要快時,則不使用索引。例如如果 key_part1均勻分佈在1和100之間,下列查詢中使用索引就不是很好:
SELECT * FROM table_name where key_part1 > 1 and key_part1 < 90
如果使用HEAP表且不用=搜尋所有鍵碼部分。
在 HEAP表上使用ORDER BY。
如果不是用鍵碼第一部分
SELECT * FROM table_name WHERE key_part2=1
如果使用以一個萬用字元開始的LIKE
SELECT * FROM table_name WHERE key_part1 LIKE '%jani%'
搜尋一個索引而在另一個索引上做ORDER BY
SELECT * from table_name WHERE key_part1 = # ORDER BY key2
--------------------------------------------------------------------------------
二十四、學會使用EXPLAIN
對於每一條你認為太慢的查詢使用EXPLAIN!
mysql> explain select t3.DateOfAction, t1.TransactionID
-> from t1 join t2 join t3
-> where t2.ID = t1.TransactionID and t3.ID = t2.GroupID
-> order by t3.DateOfAction, t1.TransactionID;
+-------+--------+---------------+---------+---------+------------------+------+---------------------------------+
| table | type | possible_keys | key | key_len | ref | rows | Extra |
+-------+--------+---------------+---------+---------+------------------+------+---------------------------------+
| t1 | ALL | NULL | NULL | NULL | NULL | 11 | Using temporary; Using filesort |
| t2 | ref | ID | ID | 4 | t1.TransactionID | 13 | |
| t3 | eq_ref | PRIMARY | PRIMARY | 4 | t2.GroupID | 1 | |
+-------+--------+---------------+---------+---------+------------------+------+---------------------------------+
ALL和範圍型別提示一個潛在的問題。
--------------------------------------------------------------------------------
二十五、學會使用SHOW PROCESSLIST
使用SHOW processlist來發現正在做什麼:
+----+-------+-----------+----+---------+------+--------------+-------------------------------------+
| Id | User | Host | db | Command | Time | State | Info |
+----+-------+-----------+----+---------+------+--------------+-------------------------------------+
| 6 | monty | localhost | bp | Query | 15 | Sending data | select * from station,station as s1 |
| 8 | monty | localhost | | Query | 0 | | show processlist |
+----+-------+-----------+----+---------+------+--------------+-------------------------------------+
在mysql或mysqladmin中用KILL來殺死溜掉的執行緒。
--------------------------------------------------------------------------------
二十六、如何知曉MySQL解決一條查詢
執行項列命令並試圖弄明白其輸出:
SHOW VARIABLES;
SHOW COLUMNS FROM ...G
EXPLAIN SELECT ...G
FLUSH STATUS;
SELECT ...;
SHOW STATUS;
--------------------------------------------------------------------------------
二十七、MySQL非常不錯
日誌
在進行很多連線時,連線非常快。
同時使用SELECT和 INSERT的場合。
在不把更新與耗時太長的選擇結合時。
在大多數選擇/更新使用唯一鍵碼時。
在使用沒有長時間衝突鎖定的 多個表時。
在用大表時(MySQL使用一個非常緊湊的表格式)。
--------------------------------------------------------------------------------
二十八、MySQL應避免的事情
用刪掉的行更新或插入表,結合要耗時長的SELECT。
在能放在 WHERE子句中的列上用HAVING。
不使用鍵碼或鍵碼不夠唯一而進行JOIN。
在不同列型別的列上JOIN。
在不使 用=匹配整個鍵碼時使用HEAP表。
在MySQL監控程式中忘記在UPDATE或DELETE中使用一條WHERE子句。如果想這樣做,使用 mysql客戶程式的--i-am-a-dummy選項。
--------------------------------------------------------------------------------
二十九、MySQL各種鎖定
內部表鎖定
LOCK TABLES(所有表型別適用)
GET LOCK()/RELEASE LOCK()
頁面鎖定(對BDB表)
ALTER TABLE也在BDB表上進行表鎖定
LOCK TABLES允許一個表有多個讀者和一個寫者。
一般WHERE鎖定具有比READ鎖定高的優先順序以避免讓寫入方乾等。對於不重要的寫入方,可 以使用LOW_PRIORITY關鍵字讓鎖定處理器優選讀取方。
UPDATE LOW_PRIORITY SET value=10 WHERE id=10;
--------------------------------------------------------------------------------
三十、給MySQL更多資訊以更好地解決問題的技巧
注意你總能去掉(加註釋)MySQL功能以使查詢可移植:
SELECT /*! SQL_BUFFER_RESULTS */ ...
SELECT SQL_BUFFER_RESULTS ...
將強制 MySQL生成一個臨時結果集。只要所有臨時結果集生成後,所有表上的鎖定均被釋放。這能在遇到表鎖定問題時或要花很長時間將結果傳給客戶端時有所幫助。
SELECT SQL_SMALL_RESULT ... GROUP BY ...
告訴優化器結果集將只包含很少的行。
SELECT SQL_BIG_RESULT ... GROUP BY ...
告訴優化器結果集將包含很多行。
SELECT STRAIGHT_JOIN ...
強制優化器以出現在FROM子句中的次序聯結表。
SELECT ... FROM table_name [USE INDEX (index_list) | IGNORE INDEX (index_list)] table_name2
強制MySQL使用/忽略列出的索引。
--------------------------------------------------------------------------------
三十一、事務的例子
MyIASM表如何進行事務處理:
mysql> LOCK TABLES trans READ, customer WRITE;
mysql> select sum(value) from trans where customer_id=some_id;
mysql> update customer set total_value=sum_from_previous_statement
where customer_id=some_id;
mysql> UNLOCK TABLES;
BDB表如何進行事務:
mysql> BEGIN WORK;
mysql> select sum(value) from trans where customer_id=some_id;
mysql> update customer set total_value=sum_from_previous_statement
where customer_id=some_id;
mysql> COMMIT;
注意你可以通過下列語句迴避事務:
UPDATE customer SET value=value+new_value WHERE customer_id=some_id;
--------------------------------------------------------------------------------
三十二、使用REPLACE的例子
REPLACE的功能極像INSERT,除了如果一條老記錄在一個唯一索引上具有 與新紀錄相同的值,那麼老記錄在新紀錄插入前則被刪除。不使用
SELECT 1 FROM t1 WHERE key=#
IF found-row
LOCK TABLES t1
DELETE FROM t1 WHERE key1=#
INSERT INTO t1 VALUES (...)
UNLOCK TABLES t1;
ENDIF
而用
REPLACE INTO t1 VALUES (...)
--------------------------------------------------------------------------------
三十三、一般技巧
使用短主鍵。聯結表時使用數字而非字串。
當使用多部分鍵碼時,第一部分應該時最常用的 部分。
有疑問時,首先使用更多重複的列以獲得更好地鍵碼壓縮。
如果在同一臺機器上執行MySQL客戶和伺服器,那麼在連線MySQL 時則使用套接字而不是TCP/IP(這可以提高效能7.5%)。可在連線MySQL伺服器時不指定主機名或主機名為localhost來做到。
如 果可能,使用--skip-locking(在某些OS上為預設),這將關閉外部鎖定並將提高效能。
使用應用層雜湊值而非長鍵碼:
SELECT * FROM table_name WHERE hash=MD5(concat(col1,col2)) AND
col_1='constant' AND col_2='constant'
在檔案中儲存需要以檔案形式訪問的BLOB,在資料庫中 只儲存檔名。
刪除所有行比刪除一大部分行要快。
如果SQL不夠快,研究一下訪問資料的較底層介面。
--------------------------------------------------------------------------------
三十四、使用MySQL 3.23的好處
MyISAM:可移植的大表格式
HEAP:記憶體中的表
Berkeley DB:支援事務的表。
眾多提高的限制
動態字符集
更多的STATUS變數
CHECK和REPAIR表
更 快的GROUP BY和DISTINCT
LEFT JOIN ... IF NULL的優化
CREATE TABLE ... SELECT
CREATE TEMPORARY table_name (...)
臨時HEAP表到MyISAM表的自動轉換
復 制
mysqlhotcopy指令碼
--------------------------------------------------------------------------------
三十五、正在積極開發的重要功能
改進事務處理
失敗安全的複製
正文搜尋
多個表的刪除 (之後完成多個表的更新)
更好的鍵碼快取
原子RENAME (RENAME TABLE foo as foo_old, foo_new as foo)
查詢快取記憶體
MERGE TABLES
一個更好的GUI客戶程式
come from:http://www.oschina.net/bbs/thread/3680
作者:晏子 (2001-05-14 12:20:05)
一、我們可以且應該優化什 麼?
硬體
作業系統/軟體庫
SQL伺服器(設定和查詢)
應用程式設計介面(API)
應用程式
--------------------------------------------------------------------------------
二、優化硬體
如果你需要龐大的資料庫表(>2G),你應該考慮使用64位的硬體結構,像Alpha、 Sparc或即將推出的IA64。因為MySQL內部使用大量64位的整數,64位的CPU將提供更好的效能。
對大資料庫,優化的次序 一般是RAM、快速硬碟、CPU能力。
更多的記憶體通過將最常用的鍵碼頁面存放在記憶體中可以加速鍵碼的更新。
如果不使 用事務安全(transaction-safe)的表或有大表並且想避免長檔案檢查,一臺UPS就能夠在電源故障時讓系統安全關閉。
對 於資料庫存放在一個專用伺服器的系統,應該考慮1G的乙太網。延遲與吞吐量同樣重要。
--------------------------------------------------------------------------------
三、優化磁碟
為系統、程式和臨時檔案配備一個專用磁碟,如果確是進行很多修改工作,將更新日誌和事務日誌放在專用磁 盤上。
低 尋道時間對資料庫磁碟非常重要。對與大表,你可以估計你將需要log(行數)/log(索引塊長度/3*2/(鍵碼長度 + 資料指標長度))+1次尋到才能找到一行。對於有500000行的表,索引Mediun int型別的列,需要log(500000) / log(1024/3*2/(3 + 2))+1=4次尋道。上述索引需要500000*7*3/2=5.2M的空間。實際上,大多數塊將被快取,所以大概只需要1-2次尋道。
然而 對於寫入(如上),你將需要4次尋道請求來找到在哪裡存放新鍵碼,而且一般要2次尋道來更新索引並寫入一行。
對於非常大的資料庫,你的應用將受 到磁碟尋道速度的限制,隨著資料量的增加呈N log N資料級遞增。
將資料庫和表分在不同的磁碟上。在MySQL中,你可以為此而使用符號鏈 接。
條列磁碟(RAID 0)將提高讀和寫的吞吐量。
帶映象的條列(RAID 0+1)將更安全並提高讀取的吞吐量。寫入的吞吐量將有所降低。
不要對臨時檔案或可以很容易地重建的資料所在的磁碟使用映象或RAID(除了 RAID 0)。
在Linux上,在引導時對磁碟使用命令hdparm -m16 -d1以啟用同時讀寫多個扇區和DMA功能。這可以將響應時間提高5~50%。
在Linux上,用async (預設)和noatime掛載磁碟(mount)。
對於某些特定應用,可以對某些特定表使用記憶體磁碟,但通常不需要。
--------------------------------------------------------------------------------
四、優化作業系統
不要交換區。如果記憶體不足,增加更多的記憶體或配置你的系統使用較少記憶體。
不要使用NFS 磁碟(會有NFS鎖定的問題)。
增加系統和MySQL伺服器的開啟檔案數量。(在safe_mysqld指令碼中加入ulimit -n #)。
增加系統的程式和執行緒數量。
如果你有相對較少的大表,告訴檔案系統不要將檔案打碎在不同的磁軌上(Solaris)。
使用 支援大檔案的檔案系統(Solaris)。
選擇使用哪種檔案系統。在Linux上的Reiserfs對於開啟、讀寫都非常快。檔案檢查只需幾秒 種。
--------------------------------------------------------------------------------
五、選擇應用程式設計介面
PERL
可在不同的作業系統和資料庫之間移植。
適宜快速原型。
應 該使用DBI/DBD介面。
PHP
比PERL易學。
使用比PERL少的資源。
通過升級到PHP4可以獲得更快的 速度。
C
MySQL的原生介面。
較快並賦予更多的控制。
低層,所以必須付出更多。
C++
較 高層次,給你更多的時間來編寫應用。
仍在開發中
ODBC
執行在Windows和Unix上。
幾乎可在不同的 SQL伺服器間移植。
較慢。MyODBC只是簡單的直通驅動程式,比用原生介面慢19%。
有很多方法做同樣的事。很難像很多ODBC 驅動程式那樣執行,在不同的領域還有不同的錯誤。
問題成堆。Microsoft偶爾還會改變介面。
不明朗的未 來。(Microsoft更推崇OLE而非ODBC)
ODBC
執行在Windows和Unix上。
幾乎可在不同的SQL服 務器間移植。
較慢。MyODBC只是簡單的直通驅動程式,比用原生介面慢19%。
有很多方法做同樣的事。很難像很多ODBC驅動程式 那樣執行,在不同的領域還有不同的錯誤。
問題成堆。Microsoft偶爾還會改變介面。
不明朗的未來。(Microsoft更推崇 OLE而非ODBC)
JDBC
理論上可在不同的作業系統何時據庫間移植。
可以執行在web客戶端。
Python 和其他
可能不錯,可我們不用它們。
--------------------------------------------------------------------------------
六、優化應用
應該集中精力解決問題。
在編寫應用時,應該決定什麼是最重要的:
速度
操 作系統間的可移植性
SQL伺服器間的可移植性
使用持續的連線。.
快取應用中的資料以減少SQL伺服器的負載。
不 要查詢應用中不需要的列。
不要使用SELECT * FROM table_name...
測試應用的所有部分,但將大部分精力放在 在可能最壞的合理的負載下的測試整體應用。通過以一種模組化的方式進行,你應該能用一個快速“啞模組”替代找到的瓶頸,然後很容易地標出下一個瓶頸。
如 果在一個批處理中進行大量修改,使用LOCK TABLES。例如將多個UPDATES或DELETES集中在一起。
--------------------------------------------------------------------------------
七、應該使用可移植的應用
Perl DBI/DBD
ODBC
JDBC
Python(或 其他有普遍SQL介面的語言)
你應該只使用存在於所有目的SQL伺服器中或可以很容易地用其他構造模擬的SQL構 造。[url]www.mysql.com上的Crash-me頁可以幫助你。[/url]
為作業系統/SQL伺服器編寫包裝程式來提供缺少的 功能。
--------------------------------------------------------------------------------
八、如果你需要更快的速度,你應該:
找出瓶頸(CPU、磁碟、記憶體、SQL伺服器、作業系統、API或應用)並集中 全力解決。
使用給予你更快速度/靈活性的擴充套件。
逐漸瞭解SQL伺服器以便能為你的問題使用可能最快的SQL構造並避免瓶頸。
優 化表佈局和查詢。
使用複製以獲得更快的選擇(select)速度。
如果你有一個慢速的網路連線資料庫,使用壓縮客戶/伺服器協議。
不 要害怕時應用的第一個版本不能完美地移植,在你解決問題時,你總是可以在以後優化它。
--------------------------------------------------------------------------------
九、優化MySQL
挑選編譯器和編譯選項。
位你的系統尋找最好的啟動選項。
通讀MySQL參考 手冊並閱讀Paul DuBios的《MySQL》一書。(已有中文版-譯註)
多用EXPLAIN SELECT、SHOW VARIABLES、SHOW STATUS和SHOW PROCESSLIST。
瞭解查詢優化器的工作原理。
優化表的格式。
維 護你的表(myisamchk、CHECK TABLE、 OPTIMIZE TABLE)
使用MySQL的擴充套件功能以讓一切快速完成。
如 果你注意到了你將在很多場合需要某些函式,編寫MySQL UDF函式。
不要使用表級或列級的GRANT,除非你確實需要。
購買 MySQL技術支援以幫助你解決問題:)
--------------------------------------------------------------------------------
十、編譯和安裝MySQL
通過位你的系統挑選可能最好的編譯器,你通常可以獲得10-30%的效能提高。
在 Linux/Intel平臺上,用pgcc(gcc的奔騰晶片優化版)編譯MySQL。然而,二進位制程式碼將只能執行在Intel奔騰CPU上。
對 於一種特定的平臺,使用MySQL參考手冊上推薦的優化選項。
一般地,對特定CPU的原生編譯器(如Sparc的Sun Workshop)應該比gcc提供更好的效能,但不總是這樣。
用你將使用的字符集編譯MySQL。
靜態編譯生成mysqld的執行 檔案(用--with-mysqld-ldflags=all-static)並用strip sql/mysqld整理最終的執行檔案。
注 意,既然MySQL不使用C++擴充套件,不帶擴充套件支援編譯MySQL將贏得巨大的效能提高。
如果作業系統支援原生執行緒,使用原生執行緒(而不用 mit-pthreads)。
用MySQL基準測試來測試最終的二進位制程式碼。
--------------------------------------------------------------------------------
十一、維護
如果可能,偶爾執行一下OPTIMIZE table,這對大量更新的變長行非常重要。
偶爾用 myisamchk -a更新一下表中的鍵碼分佈統計。記住在做之前關掉MySQL。
如果有碎片檔案,可能值得將所有檔案複製到另一個磁碟上, 清除原來的磁碟並拷迴檔案。
如果遇到問題,用myisamchk或CHECK table檢查表。
用mysqladmin -i10 precesslist extended-status監控MySQL的狀態。
用MySQL GUI客戶程式,你可以在不同的視窗內監控程式列表和狀態。
使用mysqladmin debug獲得有關鎖定和效能的資訊。
--------------------------------------------------------------------------------
十二、優化SQL
揚SQL之長,其它事情交由應用去做。使用SQL伺服器來做:
找出基於 WHERE子句的行。
JOIN表
GROUP BY
ORDER BY
DISTINCT
不要使用SQL來 做:
檢驗資料(如日期)
成為一隻計算器
技巧:
明智地使用鍵碼。
鍵碼適合搜尋,但不適 合索引列的插入/更新。
保持資料為資料庫第三正規化,但不要擔心冗餘資訊或這如果你需要更快的速度,建立總結表。
在大表上不做 GROUP BY,相反建立大表的總結表並查詢它。
UPDATE table set count=count+1 where key_column=constant非常快。
對於大表,或許最好偶爾生成總結表而不是一直保持總結表。
充分利用INSERT的默 認值。
--------------------------------------------------------------------------------
十三、不同SQL伺服器的速度差別(以秒計)
通過鍵碼讀取2000000行: NT Linux
mysql 367 249
mysql_odbc 464
db2_odbc 1206
informix_odbc 121126
ms-sql_odbc 1634
oracle_odbc 20800
solid_odbc 877
sybase_odbc 17614
插入350768行: NT Linux
mysql 381 206
mysql_odbc 619
db2_odbc 3460
informix_odbc 2692
ms-sql_odbc 4012
oracle_odbc 11291
solid_odbc 1801
sybase_odbc 4802
在上述測試中,MySQL配置8M快取記憶體執行,其他資料庫以預設安裝執行。
--------------------------------------------------------------------------------
十四、重要的MySQL啟動選項
back_log 如果需要大量新連線,修改它。
thread_cache_size 如果需要大量新連線,修改它。
key_buffer_size 索引頁池,可以設成很大。
bdb_cache_size BDB表使用的記錄和鍵嗎快取記憶體。
table_cache 如果有很多的表和併發連線,修改它。
delay_key_write 如果需要快取所有鍵碼寫入,設定它。
log_slow_queries 找出需花大量時間的查詢。
max_heap_table_size 用於GROUP BY
sort_buffer 用於ORDER BY和GROUP BY
myisam_sort_buffer_size 用於REPAIR TABLE
join_buffer_size 在進行無鍵嗎的聯結時使用。
--------------------------------------------------------------------------------
十五、優化表
MySQL擁有一套豐富的型別。你應該對每一列嘗試使用最有效的型別。
ANALYSE過程可 以幫助你找到表的最優型別:SELECT * FROM table_name PROCEDURE ANALYSE()。
對於不儲存NULL 值的列使用NOT NULL,這對你想索引的列尤其重要。
將ISAM型別的表改為MyISAM。
如果可能,用固定的表格式建立表。
不 要索引你不想用的東西。
利用MySQL能按一個索引的字首進行查詢的事實。如果你有索引INDEX(a,b),你不需要在a上的索引。
不 在長CHAR/VARCHAR列上建立索引,而只索引列的一個字首以節省儲存空間。CREATE TABLE table_name (hostname CHAR(255) not null, index(hostname(10)))
對每個表使用最有效的表格式。
在不同表中儲存 相同資訊的列應該有同樣的定義並具有相同的列名。
--------------------------------------------------------------------------------
十六、MySQL如何次儲存資料
資料庫以目錄儲存。
表以檔案儲存。
列以變長或定長格式儲存在文 件中。對BDB表,資料以頁面形式儲存。
支援基於記憶體的表。
資料庫和表可在不同的磁碟上用符號連線起來。
在Windows 上,MySQL支援用.sym檔案內部符號連線資料庫。
--------------------------------------------------------------------------------
十七、MySQL表型別
HEAP表:固定行長的表,只儲存在記憶體中並用HASH索引進行索引。
ISAM 表:MySQL 3.22中的早期B-tree表格式。
MyIASM:IASM表的新版本,有如下擴充套件:
二進位制層次的可移植性。
NULL 列索引。
對變長行比ISAM表有更少的碎片。
支援大檔案。
更好的索引壓縮。
更好的鍵嗎統計分佈。
更好 和更快的auto_increment處理。
來自Sleepcat的Berkeley DB(BDB)表:事務安全(有BEGIN WORK/COMMIT|ROLLBACK)。
--------------------------------------------------------------------------------
十八、MySQL行型別(專指IASM/MyIASM表)
如果所有列是定長格式(沒有VARCHAR、BLOB或 TEXT),MySQL將以定長表格式建立表,否則表以動態長度格式建立。
定長格式比動態長度格式快很多並更安全。
動態長度行格式一 般佔用較少的儲存空間,但如果表頻繁更新,會產生碎片。
在某些情況下,不值得將所有VARCHAR、BLOB和TEXT列轉移到另一個表中,只 是獲得主表上的更快速度。
利用myiasmchk(對ISAM,pack_iasm),可以建立只讀壓縮表,這使磁碟使用率最小,但使用慢速磁 盤時,這非常不錯。壓縮表充分地利用將不再更新的日誌表
--------------------------------------------------------------------------------
十九、MySQL快取記憶體(所有執行緒共享,一次性分配)
鍵碼快取:key_buffer_size,預設8M。
表 快取:table_cache,預設64。
執行緒快取:thread_cache_size,預設0。
主機名快取:可在編譯時修改,默 認128。
記憶體對映表:目前僅用於壓縮表。
注意:MySQL沒有行快取記憶體,而讓作業系統處理。
--------------------------------------------------------------------------------
二十、MySQL快取區變數(非共享,按需分配)
sort_buffer:ORDER BY/GROUP BY
record_buffer: 掃描表。
join_buffer_size:無鍵聯結
myisam_sort_buffer_size:REPAIR TABLE
net_buffer_length: 對於讀SQL語句並快取結果。
tmp_table_size:臨時結果的HEAP表大小。
--------------------------------------------------------------------------------
二十一、MySQL表快取記憶體工作原理
每個MyISAM表的開啟例項(instance)使用一個索引檔案和一個數 據檔案。如果表被兩個執行緒使用或在同一條查詢中使用兩次,MyIASM將共享索引檔案而是開啟資料檔案的另一個例項。
如果所有在快取記憶體中的表 都在使用,快取將臨時增加到比表快取尺寸大些。如果是這樣,下一個被釋放的表將被關閉。
你可以通過檢查mysqld的 Opened_tables變數以檢查表快取是否太小。如果該值太高,你應該增大表快取記憶體。
--------------------------------------------------------------------------------
二十二、MySQL擴充套件/優化-提供更快的速度
使用優化的表型別(HEAP、MyIASM或BDB表)。
對 資料使用優化的列。
如果可能使用定長行。
使用不同的鎖定型別(SELECT HIGH_PRIORITY,INSERT LOW_PRIORITY)
Auto_increment
REPLACE (REPLACE INTO table_name VALUES (...))
INSERT DELAYED
LOAD DATA INFILE / LOAD_FILE()
使 用多行INSERT一次插入多行。
SELECT INTO OUTFILE
LEFT JOIN, STRAIGHT JOIN
LEFT JOIN ,結合IS NULL
ORDER BY可在某些情況下使用鍵碼。
如果只查詢在一個索引中的列,將只使用索引樹解決查詢。
聯結一般比子查詢快(對大多數SQL伺服器亦如此)。
LIMIT
SELECT * from table1 WHERE a > 10 LIMIT 10,20
DELETE * from table1 WHERE a > 10 LIMIT 10
foo IN (常數列表) 高度優化。
GET_LOCK()/RELEASE_LOCK()
LOCK TABLES
INSERT 和SELECT可同時執行。
UDF函式可裝載進一個正在執行的伺服器。
壓縮只讀表。
CREATE TEMPORARY TABLE
CREATE TABLE .. SELECT
帶RAID選項的MyIASM表將檔案分割成很多檔案以突破某些檔案系統的 2G限制。
Delay_keys
複製功能
--------------------------------------------------------------------------------
二十二、MySQL何時使用索引
對一個鍵碼使用>, >=, =,
SELECT * FROM table_name WHERE key_part1=1 and key_part2 > 5;
SELECT * FROM table_name WHERE key_part1 IS NULL;
當使用不以萬用字元開始的LIKE
SELECT * FROM table_name WHERE key_part1 LIKE 'jani%'
在進行聯結時從另一個表中提取行時
SELECT * from t1,t2 where t1.col=t2.key_part
找出指定索引的MAX()或MIN()值
SELECT MIN(key_part2),MAX(key_part2) FROM table_name where key_part1=10
一個鍵 碼的字首使用ORDER BY或GROUP BY
SELECT * FROM foo ORDER BY key_part1,key_part2,key_part3
在所有用在查詢中的列是鍵碼的一部分時間
SELECT key_part3 FROM table_name WHERE key_part1=1
--------------------------------------------------------------------------------
二十三、MySQL何時不使用索引
如果MySQL能估計出它將可能比掃描整張表還要快時,則不使用索引。例如如果 key_part1均勻分佈在1和100之間,下列查詢中使用索引就不是很好:
SELECT * FROM table_name where key_part1 > 1 and key_part1 < 90
如果使用HEAP表且不用=搜尋所有鍵碼部分。
在 HEAP表上使用ORDER BY。
如果不是用鍵碼第一部分
SELECT * FROM table_name WHERE key_part2=1
如果使用以一個萬用字元開始的LIKE
SELECT * FROM table_name WHERE key_part1 LIKE '%jani%'
搜尋一個索引而在另一個索引上做ORDER BY
SELECT * from table_name WHERE key_part1 = # ORDER BY key2
--------------------------------------------------------------------------------
二十四、學會使用EXPLAIN
對於每一條你認為太慢的查詢使用EXPLAIN!
mysql> explain select t3.DateOfAction, t1.TransactionID
-> from t1 join t2 join t3
-> where t2.ID = t1.TransactionID and t3.ID = t2.GroupID
-> order by t3.DateOfAction, t1.TransactionID;
+-------+--------+---------------+---------+---------+------------------+------+---------------------------------+
| table | type | possible_keys | key | key_len | ref | rows | Extra |
+-------+--------+---------------+---------+---------+------------------+------+---------------------------------+
| t1 | ALL | NULL | NULL | NULL | NULL | 11 | Using temporary; Using filesort |
| t2 | ref | ID | ID | 4 | t1.TransactionID | 13 | |
| t3 | eq_ref | PRIMARY | PRIMARY | 4 | t2.GroupID | 1 | |
+-------+--------+---------------+---------+---------+------------------+------+---------------------------------+
ALL和範圍型別提示一個潛在的問題。
--------------------------------------------------------------------------------
二十五、學會使用SHOW PROCESSLIST
使用SHOW processlist來發現正在做什麼:
+----+-------+-----------+----+---------+------+--------------+-------------------------------------+
| Id | User | Host | db | Command | Time | State | Info |
+----+-------+-----------+----+---------+------+--------------+-------------------------------------+
| 6 | monty | localhost | bp | Query | 15 | Sending data | select * from station,station as s1 |
| 8 | monty | localhost | | Query | 0 | | show processlist |
+----+-------+-----------+----+---------+------+--------------+-------------------------------------+
在mysql或mysqladmin中用KILL來殺死溜掉的執行緒。
--------------------------------------------------------------------------------
二十六、如何知曉MySQL解決一條查詢
執行項列命令並試圖弄明白其輸出:
SHOW VARIABLES;
SHOW COLUMNS FROM ...G
EXPLAIN SELECT ...G
FLUSH STATUS;
SELECT ...;
SHOW STATUS;
--------------------------------------------------------------------------------
二十七、MySQL非常不錯
日誌
在進行很多連線時,連線非常快。
同時使用SELECT和 INSERT的場合。
在不把更新與耗時太長的選擇結合時。
在大多數選擇/更新使用唯一鍵碼時。
在使用沒有長時間衝突鎖定的 多個表時。
在用大表時(MySQL使用一個非常緊湊的表格式)。
--------------------------------------------------------------------------------
二十八、MySQL應避免的事情
用刪掉的行更新或插入表,結合要耗時長的SELECT。
在能放在 WHERE子句中的列上用HAVING。
不使用鍵碼或鍵碼不夠唯一而進行JOIN。
在不同列型別的列上JOIN。
在不使 用=匹配整個鍵碼時使用HEAP表。
在MySQL監控程式中忘記在UPDATE或DELETE中使用一條WHERE子句。如果想這樣做,使用 mysql客戶程式的--i-am-a-dummy選項。
--------------------------------------------------------------------------------
二十九、MySQL各種鎖定
內部表鎖定
LOCK TABLES(所有表型別適用)
GET LOCK()/RELEASE LOCK()
頁面鎖定(對BDB表)
ALTER TABLE也在BDB表上進行表鎖定
LOCK TABLES允許一個表有多個讀者和一個寫者。
一般WHERE鎖定具有比READ鎖定高的優先順序以避免讓寫入方乾等。對於不重要的寫入方,可 以使用LOW_PRIORITY關鍵字讓鎖定處理器優選讀取方。
UPDATE LOW_PRIORITY SET value=10 WHERE id=10;
--------------------------------------------------------------------------------
三十、給MySQL更多資訊以更好地解決問題的技巧
注意你總能去掉(加註釋)MySQL功能以使查詢可移植:
SELECT /*! SQL_BUFFER_RESULTS */ ...
SELECT SQL_BUFFER_RESULTS ...
將強制 MySQL生成一個臨時結果集。只要所有臨時結果集生成後,所有表上的鎖定均被釋放。這能在遇到表鎖定問題時或要花很長時間將結果傳給客戶端時有所幫助。
SELECT SQL_SMALL_RESULT ... GROUP BY ...
告訴優化器結果集將只包含很少的行。
SELECT SQL_BIG_RESULT ... GROUP BY ...
告訴優化器結果集將包含很多行。
SELECT STRAIGHT_JOIN ...
強制優化器以出現在FROM子句中的次序聯結表。
SELECT ... FROM table_name [USE INDEX (index_list) | IGNORE INDEX (index_list)] table_name2
強制MySQL使用/忽略列出的索引。
--------------------------------------------------------------------------------
三十一、事務的例子
MyIASM表如何進行事務處理:
mysql> LOCK TABLES trans READ, customer WRITE;
mysql> select sum(value) from trans where customer_id=some_id;
mysql> update customer set total_value=sum_from_previous_statement
where customer_id=some_id;
mysql> UNLOCK TABLES;
BDB表如何進行事務:
mysql> BEGIN WORK;
mysql> select sum(value) from trans where customer_id=some_id;
mysql> update customer set total_value=sum_from_previous_statement
where customer_id=some_id;
mysql> COMMIT;
注意你可以通過下列語句迴避事務:
UPDATE customer SET value=value+new_value WHERE customer_id=some_id;
--------------------------------------------------------------------------------
三十二、使用REPLACE的例子
REPLACE的功能極像INSERT,除了如果一條老記錄在一個唯一索引上具有 與新紀錄相同的值,那麼老記錄在新紀錄插入前則被刪除。不使用
SELECT 1 FROM t1 WHERE key=#
IF found-row
LOCK TABLES t1
DELETE FROM t1 WHERE key1=#
INSERT INTO t1 VALUES (...)
UNLOCK TABLES t1;
ENDIF
而用
REPLACE INTO t1 VALUES (...)
--------------------------------------------------------------------------------
三十三、一般技巧
使用短主鍵。聯結表時使用數字而非字串。
當使用多部分鍵碼時,第一部分應該時最常用的 部分。
有疑問時,首先使用更多重複的列以獲得更好地鍵碼壓縮。
如果在同一臺機器上執行MySQL客戶和伺服器,那麼在連線MySQL 時則使用套接字而不是TCP/IP(這可以提高效能7.5%)。可在連線MySQL伺服器時不指定主機名或主機名為localhost來做到。
如 果可能,使用--skip-locking(在某些OS上為預設),這將關閉外部鎖定並將提高效能。
使用應用層雜湊值而非長鍵碼:
SELECT * FROM table_name WHERE hash=MD5(concat(col1,col2)) AND
col_1='constant' AND col_2='constant'
在檔案中儲存需要以檔案形式訪問的BLOB,在資料庫中 只儲存檔名。
刪除所有行比刪除一大部分行要快。
如果SQL不夠快,研究一下訪問資料的較底層介面。
--------------------------------------------------------------------------------
三十四、使用MySQL 3.23的好處
MyISAM:可移植的大表格式
HEAP:記憶體中的表
Berkeley DB:支援事務的表。
眾多提高的限制
動態字符集
更多的STATUS變數
CHECK和REPAIR表
更 快的GROUP BY和DISTINCT
LEFT JOIN ... IF NULL的優化
CREATE TABLE ... SELECT
CREATE TEMPORARY table_name (...)
臨時HEAP表到MyISAM表的自動轉換
復 制
mysqlhotcopy指令碼
--------------------------------------------------------------------------------
三十五、正在積極開發的重要功能
改進事務處理
失敗安全的複製
正文搜尋
多個表的刪除 (之後完成多個表的更新)
更好的鍵碼快取
原子RENAME (RENAME TABLE foo as foo_old, foo_new as foo)
查詢快取記憶體
MERGE TABLES
一個更好的GUI客戶程式
come from:http://www.oschina.net/bbs/thread/3680
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/90618/viewspace-625656/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 非常好的MySQL最佳化(轉)MySql
- linux效能優化(轉帖)Linux優化
- [轉]轉一個關於優化sql的文章優化SQL
- 一篇文章搞定 MySQL 索引優化MySql索引優化
- (轉)MySQL優化例項MySql優化
- 【轉】MySQL 建表的優化策略 小結MySql優化
- 轉一篇關於JAVA 和 .NET的文章的比較Java
- 一篇不錯的講解Java異常的文章(轉)Java
- [轉帖]
- 轉載 MELTAINK 一篇HANGANALZE文章AI
- shell程式設計(轉三呼的一篇文章)程式設計
- [轉帖]redis中的maxmemoryRedis
- [轉帖]mkcertmkcert
- MySQL的最佳化 (轉)MySql
- 非常經典的UNIX系統調優的文章(轉)
- [轉帖] 舌尖上的程式猿
- Flashback Query的應用(轉帖)
- RMAN命令詳解 非常好的文章
- [玩轉MySQL之六]MySQL查詢優化器MySql優化
- (轉)例項分析:MySQL優化經驗MySql優化
- [轉]MySQL 5.6 my.cnf配置優化MySql優化
- MySQL資料庫效能優化之表結構優化(轉)MySql資料庫優化
- MYSQL叢集的備份與恢復最終版本(轉帖)MySql
- 並查集詳解(轉的別人寫的一篇蠻好的文章)並查集
- expdp 和impdp的筆記[轉帖]筆記
- [轉帖]XACT_ABORT 的問題
- [轉帖]掌握udevdev
- [轉帖]海光CPU
- 【轉】ckEditor使用方法 轉帖
- MySQL資料庫效能優化之快取引數優化(轉)MySql資料庫優化快取
- 關於MySQL資料庫效能優化方法,看這一篇文章就夠了!MySql資料庫優化
- 轉METALINK一篇文章(變數窺視)變數
- Laravel 框架如何優雅的寫出文章的上一篇和下一篇Laravel框架
- mysql的優化MySql優化
- 瞭解MySQL的隱式轉化MySql
- [轉帖]SQL秘笈 : NOLOCK、ROWLOCK、UPDLOCK的使用!SQL
- [轉帖]剖析free命令
- 一篇文章帶你玩轉正規表示式