MySQL數據庫是一種小型關係型數據庫管理系統,MySQL數據庫的優化是MySQL數據庫操做過程當中很是重要的工做,MySQL數據庫的優化可以實現MySQL數據庫操做的簡便。 mysql
第一步: linux
1:磁盤尋道能力,以高速硬盤(7200轉/秒),理論上每秒尋道7200次.這是沒有辦法改變的,優化的方法是----用多個硬盤,或者把數據分散存儲. sql
2:硬盤的讀寫速度,這個速度很是的快,這個更容易解決--能夠從多個硬盤上並行讀寫. shell
3:cpu.cpu處理內存中的數據,當有相對內存較小的表時,這是最多見的限制因素. 數據庫
4:內存的限制.當cpu須要超出適合cpu緩存的數據時,緩存的帶寬就成了內存的一個瓶頸---不過如今內存大的驚人,通常不會出現這個問題. express
第二步: (本人使用的是學校網站的linux平臺(Linux ADVX.Mandrakesoft.com 2.4.3-19mdk )) 緩存
1:調節服務器參數 安全
用shell>mysqld-help這個命令聲廠一張全部mysql選項和可配置變量的表.輸出如下信息: 服務器
possible variables for option--set-variable(-o) are: mysql優化
back_log current value:5 //要求mysql能有的鏈接數量.back_log指出在mysql暫停接受鏈接的時間內有多少個鏈接請求能夠被存在堆棧中
connect_timeout current value:5 //mysql服務器在用bad handshake(很差翻譯)應答前等待一個鏈接的時間
delayed_insert_timeout current value:200 //一個insert delayed在終止前等待insert的時間
delayed_insert_limit current value:50 //insert delayed處理器將檢查是否有任何select語句未執行,若是有,繼續前執行這些語句
delayed_queue_size current value:1000 //爲insert delayed分配多大的隊
flush_time current value:0 //若是被設置爲非0,那麼每一個flush_time 時間,全部表都被關閉
interactive_timeout current value:28800 //服務器在關上它以前在洋交互鏈接上等待的時間
join_buffer_size current value:131072 //用與所有鏈接的緩衝區大小
key_buffer_size current value:1048540 //用語索引塊的緩衝區的大小,增長它能夠更好的處理索引
lower_case_table_names current value:0 //
long_query_time current value:10 //若是一個查詢所用時間大於此時間,slow_queried計數將增長
max_allowed_packet current value:1048576 //一個包的大小
max_connections current value:300 //容許同時鏈接的數量
max_connect_errors current value:10 //若是有多於該數量的中斷鏈接,將阻止進一步的鏈接,能夠用flush hosts來解決
max_delayed_threads current value:15 //能夠啓動的處理insert delayed的數量
max_heap_table_size current value:16777216 //
max_join_size current value:4294967295 //容許讀取的鏈接的數量
max_sort_length current value:1024 //在排序blob或者text時使用的字節數量
max_tmp_tables current value:32 //一個鏈接同時打開的臨時表的數量
max_write_lock_count current value:4294967295 //指定一個值(一般很小)來啓動mysqld,使得在必定數量的write鎖定以後出現read鎖定
net_buffer_length current value:16384 //通訊緩衝區的大小--在查詢時被重置爲該大小
query_buffer_size current value:0 //查詢時緩衝區大小
record_buffer current value:131072 //每一個順序掃描的鏈接爲其掃描的每張表分配的緩衝區的大小
sort_buffer current value:2097116 //每一個進行排序的鏈接分配的緩衝區的大小
table_cache current value:64 //爲全部鏈接打開的表的數量
thread_concurrency current value:10 //
tmp_table_size current value:1048576 //臨時表的大小
thread_stack current value:131072 //每一個線程的大小
wait_timeout current value:28800 //服務器在關閉它3以前的一個鏈接上等待的時間
根據本身的須要配置以上信息會對你幫助.
第三步:
1:若是你在一個數據庫中建立大量的表,那麼執行打開,關閉,建立(表)的操做就會很慢. 2:mysql使用內存
a: 關鍵字緩存區(key_buffer_size)由全部線程共享
b: 每一個鏈接使用一些特定的線程空間.一個棧(默認爲64k,變量thread_stack),一個鏈接緩衝區(變量net_buffer_length)和一個結果緩衝區(net_buffer_length).特定狀況下,鏈接緩衝區和結果緩衝區被動態擴大到max_allowed_packet.
c:全部線程共享一個基存儲器
d:沒有內存影射
e:每一個作順序掃描的請求分配一個讀緩衝區(record_buffer)
f:全部聯結均有一遍完成而且大多數聯結甚至能夠不用一個臨時表完成.最臨時的表是基於內存的(heap)表
g:排序請求分配一個排序緩衝區和2個臨時表
h:全部語法分析和計算都在一個本地存儲器完成
i:每一個索引文件只被打開一次,而且數據文件爲每一個併發運行的線程打開一次
j:對每一個blob列的表,一個緩衝區動態的被擴大以便讀入blob值
k:全部正在使用的表的表處理器被保存在一個緩衝器中而且做爲一個fifo管理.
l:一個mysqladmin flush-tables命令關閉全部不在使用的表而且在當前執行的線程結束時標記全部在使用的表準備關閉
3:mysql鎖定表
mysql中全部鎖定不會成爲死鎖. wirte鎖定: mysql的鎖定原理:a:若是表沒有鎖定,那麼鎖定;b不然,把鎖定請求放入寫鎖定隊列中
read鎖定: mysql的鎖定原理:a:若是表沒有鎖定,那麼鎖定;b不然,把鎖定請求放入讀鎖定隊列中
有時候會在一個表中進行不少的select,insert操做,能夠在一個臨時表中插入行而且偶爾用臨時表的記錄更新真正的表
a:用low_priority屬性給一個特定的insert,update或者delete較低的優先級
b:max_write_lock_count指定一個值(一般很小)來啓動mysqld,使得在必定數量的write鎖定以後出現read鎖定
c:經過使用set sql_low_priority_updates=1能夠從一個特定的線程指定全部的更改應該由較低的優先級完成
d:用high_priority指定一個select
e:若是使用insert....select....出現問題,使用myisam表------由於它支持由於它支持併發的select和insert
4:最基本的優化是使數據在硬盤上佔據的空間最小.若是索引作在最小的列上,那麼索引也最小.實現方法:
a:使用盡量小的數據類型
b:若是可能,聲明表列爲NOT NULL.
c:若是有可能使用變成的數據類型,如varchar(可是速度會受必定的影響)
d:每一個表應該有儘量短的主索引 e:建立確實須要的索引
f:若是一個索引在頭幾個字符上有惟一的前綴,那麼僅僅索引這個前綴----mysql支持在一個字符列的一部分上的索引
g:若是一個表常常被掃描,那麼試圖拆分它爲更多的表
第四步
1:索引的使用,索引的重要性就不說了,功能也不說了,只說怎麼作. 首先要明確全部的mysql索引(primary,unique,index)在b樹中有存儲.索引主要用語:
a:快速找到where指定條件的記錄 b:執行聯結時,從其餘表檢索行 c:對特定的索引列找出max()和min()值
d:若是排序或者分組在一個可用鍵的最前面加前綴,排序或分組一個表
e:一個查詢可能被用來優化檢索值,而不用訪問數據文件.若是某些表的列是數字型而且正好是某個列的前綴,爲了更快,值能夠從索引樹中取出
2:存儲或者更新數據的查詢速度 grant的執行會稍稍的減低效率.
mysql的函數應該被高度的優化.能夠用benchmark(loop_count,expression)來找出是否查詢有問題
select的查詢速度:若是想要讓一個select...where...更快,我能想到的只有創建索引.能夠在一個表上運行myisamchk--analyze來更好的優化查詢.能夠用myisamchk--sort-index--sort-records=1來設置用一個索引排序一個索引和數據.
3:mysql優化where子句
3.1:刪除沒必要要的括號:
((a AND b) AND c OR (((a AND b) AND (a AND d))))>(a AND b AND c) OR (a AND b AND c AND d)
3.2:使用常數
(ab>5 AND b=c AND a=5
3.3:刪除常數條件
(b>=5 AND b=5) OR (b=6 AND 5=5) OR (b=100 AND 2=3) >b=5 OR b=6
3.4:索引使用的常數表達式僅計算一次
3.5:在一個表中,沒有一個where的count(*)直接從表中檢索信息
3.6:全部常數的表在查詢中在任何其餘表以前讀出
3.7:對外聯結表最好聯結組合是嘗試了全部可能性找到的
3.8:若是有一個order by字句和一個不一樣的group by子句或者order by或者group by包含不是來自聯結的第一個表的列,那麼建立一個臨時表
3.9:若是使用了sql_small_result,那麼msyql使用在內存中的一個表
3.10:每一個表的索引給查詢而且使用跨越少於30%的行的索引.
3.11在每一個記錄輸出前,跳過不匹配having子句的行
4:優化left join
在mysql中 a left join b按如下方式實現
a:表b依賴於表a
b:表a依賴於全部用在left join條件的表(除了b)
c:全部left join條件被移到where子句中
d:進行全部的聯結優化,除了一個表老是在全部他依賴的表後讀取.若是有一個循環依賴,那麼將發生錯誤
e:進行全部的標準的where優化 f:若是在a中有一行匹配where子句,可是在b中沒有任何匹配left join條件,那麼,在b中生成的全部設置爲NULL的一行
g:若是使用left join來找出某些表中不存在的行而且在where部分有column_name IS NULL測試(column_name爲NOT NULL列).那麼,mysql在它已經找到了匹配left join條件的一行後,將中止在更多的行後尋找
5:優化limit
a:若是用limit只選擇一行,當mysql須要掃描整個表時,它的做用至關於索引
b:若是使用limit#與order by,mysql若是找到了第#行,將結束排序,而不會排序正個表
c:當結合limit#和distinct時,mysql若是找到了第#行,將中止
d:只要mysql已經發送了第一個#行到客戶,mysql將放棄查詢
e:limit 0一直會很快的返回一個空集合.
f:臨時表的大小使用limit#計算須要多少空間來解決查詢
6:優化insert
插入一條記錄的是由如下構成:
a:鏈接(3)
b:發送查詢給服務器(2)
c:分析查詢(2)
d:插入記錄(1*記錄大小)
e:插入索引(1*索引)
f:關閉(1)
以上數字能夠當作和總時間成比例
改善插入速度的一些方法:
6.1:若是同時從一個鏈接插入許多行,使用多個值的insert,這比用多個語句要快
6.2:若是從不一樣鏈接插入不少行,使用insert delayed語句速度更快
6.3: 用myisam,若是在表中沒有刪除的行,能在select:s正在運行的同時插入行
6.4: 當從一個文本文件裝載一個表時,用load data infile.這個一般比insert快20 倍
6.5:能夠鎖定表而後插入--主要的速度差異是在全部insert語句完成後,索引緩衝區僅被存入到硬盤一次.通常與有不一樣的insert語句那樣屢次存入要快.若是能用一個單個語句插入全部的行,鎖定就不須要.鎖定也下降鏈接的總體時間.可是對某些線程最大等待時間將上升.例如:
thread 1 does 1000 inserts
thread 2,3 and 4 does 1 insert
thread 5 does 1000 inserts
若是不使用鎖定,2,3,4將在1和5以前完成.若是使用鎖定,2,3,4,將可能在1和5以後完成.可是總體時間應該快40%.由於insert,update,delete操做在mysql中是很快的,經過爲多於大約5次接二連三的插入或更新一行的東西加鎖,將得到更好的總體性能.若是作不少一行的插入,能夠作一個lock tables,偶爾隨後作一個unlock tables(大約每1000行)以容許另外的線程存取表.這仍然將致使得到好的性能.load data infile對裝載數據仍然是很快的.
爲了對load data infile和insert獲得一些更快的速度,擴大關鍵字緩衝區.
7優化update的速度
它的速度依賴於被更新數據的大小和被更新索引的數量
使update更快的另外一個方法是推遲修改,而後一行一行的作不少修改.若是鎖定表,作一行一行的不少修改比一次作一個快
8優化delete速度
刪除一個記錄的時間與索引數量成正比.爲了更快的刪除記錄,能夠增長索引緩存的大小 從一個表刪除全部行比刪除這個表的大部分要快的多
第五步
1:選擇一種表類型 1.1靜態myisam
這種格式是最簡單且最安全的格式,它是磁盤格式中最快的.速度來自於數據能在磁盤上被找到的難易程度.當鎖定有一個索引和靜態格式的東西是,它很簡單,只是行長度乘以數量.並且在掃描一張表時,每次用磁盤讀取來讀入常數個記錄是很容易的.安全性來源於若是當寫入一個靜態myisam文件時致使計算機down掉,myisamchk很容易指出每行在哪裏開始和結束,所以,它一般能收回全部記錄,除了部分被寫入的記錄.在mysql中全部索引總能被重建
1.2動態myisam
這種格式每一行必須有一個頭說明它有多長.當一個記錄在更改期間變長時,它能夠在多於一個位置上結束.能使用optimize tablename或myisamchk整理一張表.若是在同一個表中有像某些varchar或者blob列那樣存取/改變的靜態數據,將動態列移入另一個表以免碎片.
1.2.1壓縮myisam,用可選的myisampack工具生成
1.2.2內存
這種格式對小型/中型表頗有用.對拷貝/建立一個經常使用的查找表到洋heap表有可能加快多個表聯結,用一樣數據可能要快好幾倍時間.
select tablename.a,tablename2.a from tablename,tablanem2,tablename3 where
tablaneme.a=tablename2.a and tablename2.a=tablename3.a and tablename2.c!=0;
爲了加速它,能夠用tablename2和tablename3的聯結建立一個臨時表,由於用相同列(tablename1.a)查找.
CREATE TEMPORARY TABLE test TYPE=HEAP
SELECT
tablename2.a as a2,tablename3.a as a3
FROM
tablenam2,tablename3
WHERE
tablename2.a=tablename3.a and c=0;
SELECT tablename.a,test.a3 from tablename,test where tablename.a=test.a1;
SELECT tablename.a,test,a3,from tablename,test where tablename.a=test.a1 and ....;
1.3靜態表的特色
1.3.1默認格式.用在表不包含varchar,blob,text列的時候
1.3.2全部的char,numeric和decimal列填充到列寬度
1.3.3很是快
1.3.4容易緩衝
1.3.5容易在down後重建,由於記錄位於固定的位置
1.3.6沒必要被從新組織(用myisamchk),除非是一個巨量的記錄被刪除而且優化存儲大小
1.3.7一般比動態表須要更多的存儲空間
1.4動態表的特色
1.4.1若是表包含任何varchar,blob,text列,使用該格式
1.4.2全部字符串列是動態的
1.4.3每一個記錄前置一個位.
1.4.4一般比定長表須要更多的磁盤空間
1.4.5每一個記錄僅僅使用所須要的空間,若是一個記錄變的很大,它按須要被分紅不少段,這致使了記錄碎片
1.4.6若是用超過行長度的信息更新行,行被分段.
1.4.7在系統down掉之後很差重建表,由於一個記錄能夠是多段
1.4.8對動態尺寸記錄的指望行長度是3+(number of columns+7)/8+(number of char columns)+packed size of numeric columns+length of strings +(number of NULL columns+7)/8
對每一個鏈接有6個字節的懲罰.不管什麼時候更改引發記錄的變大,都有一個動態記錄被鏈接.每一個新鏈接至少有20個字節,所以下一個變大將可能在同一個鏈接中.若是不是,將有另一個鏈接.能夠用myisamchk -惡毒檢查有多少鏈接.全部鏈接能夠用myisamchk -r刪除.
1.5壓縮表的特色
1.5.1一張用myisampack實用程序製做的只讀表.
1.5.2解壓縮代碼存在於全部mysql分發中,以便使沒有myisampack的鏈接也能讀取用myisampack壓縮的表
1.5.3佔據很小的磁盤空間
1.5.4每一個記錄被單獨壓縮.一個記錄的頭是一個定長的(1~~3個字節)這取決於表的最大記錄.每列以不一樣的方式被壓縮.一些經常使用的壓縮類型是:
a:一般對每列有一張不一樣的哈夫曼表 b:後綴空白壓縮 c:前綴空白壓縮 d:用值0的數字使用1位存儲
e:若是整數列的值有一個小範圍,列使用最小的可能類型來存儲.例如:若是全部的值在0到255之間,一個bigint能夠做爲一個tinyint存儲
g:若是列僅有可能值的一個小集合,列類型被轉換到enum h:列可使用上面的壓縮方法的組合
1.5.5能處理定長或動態長度的記錄,去不能處理blob或者text列 1.5.6能用myisamchk解壓縮
mysql能支持不一樣的索引類型,但通常的類型是isam,這是一個B樹索引而且能粗略的爲索引文件計算大小爲(key_length+4)*0.67,在全部的鍵上的總和.
字符串索引是空白壓縮的。若是第一個索引是一個字符串,它可將壓縮前綴若是字符串列有不少尾部空白或是一個總部能甬道全長的varchar列,空白壓縮使索引文件更小.若是不少字符串有相同的前綴.
1.6內存表的特色
mysql內部的heap表使用每偶溢出去的100%動態哈希而且沒有與刪除有關的問題.只能經過使用在堆表中的一個索引來用等式存取東西(一般用'='操做符)
堆表的缺點是:
1.6.1想要同時使用的全部堆表須要足夠的額外內存
1.6.2不能在索引的一個部分搜索
1.6.3不能按順序搜索下一個條目(即,使用這個索引作一個order by)
1.6.4mysql不能算出在2個值之間大概有多少行.這被優化器使用是用來決定使用哪一個索引的,可是在另外一個方面甚至不須要磁盤尋道
經過上文中介紹的這五步就可以實現MySQL數據庫的優化工做,但願你們都可以從上文中涉及到的內容中有所收穫。