l 了解什么是優化
l 掌握優化查詢的方法
l 掌握優化數據庫結構的方法
l 掌握優化MySQL服務器的方法
l 合理安排資源、調整系統參數使MySQL運行更快、更節省資源。
l 優化是多方面的,包括查詢優化、更新優化、服務器優化等很多方面。沒有特定方式特定的方法,總是要具體場景,具體分析,但是我們要掌握基本的優化手段。
l 原則:減少系統瓶頸,減少資源占用,增加系統的反應速度。
l 我們可以通過SHOWSTATUS語句查看MySQL數據庫的性能參數
? SHOW STATUS LIKE 'value‘
l 常用的參數:
? Slow_queries 慢查詢次數:
? 什么是慢查詢? mysql讀寫分離的時候的日志,里面記錄了執行某條sql語句超過某個時間后的記錄,方便我們做一個后期的優化,我們可以通過Slow_queries顯示慢查詢
查看你的mysql數據庫是否有慢查詢:SHOW STATUS LIKE 'Slow_queries'
從哪里解決呢?從日志里面去找啊這個我們需要配置的
? Com_(CRUD) 操作的次數
?
? %20Uptime %20上線時間
在MySQL中可以使用EXPLAIN查看SQL執行計劃,用法:EXPLAIN%20SELECT%20*%20FROM%20tb_item
SELECT識別符。這是SELECT查詢序列號。這個不重要。
表示查詢中每個select子句的類型(簡單%20OR復雜)。
有以下幾種值:
1、 %20SIMPLE查詢中不包含子查詢或者UNION
3、 UNION表示連接查詢的第2個或后面的查詢語句。
4、 DEPENDENT UNIONUNION中的第二個或后面的SELECT語句,取決于外面的查詢。
5、 UNION RESULT連接查詢的結果。
6、 SUBQUERY子查詢中的第1個SELECT語句。
7、 DEPENDENT SUBQUERY子查詢中的第1個SELECT語句,取決于外面的查詢。
8、 DERIVEDSELECT(FROM 子句的子查詢)。
表示查詢的表。
表示表的連接類型。
以下的連接類型的順序是從最佳類型到最差類型:
1、 system表僅有一行,這是const類型的特列,平時不會出現,這個也可以忽略不計。
2、 const數據表最多只有一個匹配行,因為只匹配一行數據,所以很快,常用于PRIMARY KEY或者UNIQUE索引的查詢,可理解為const是最優化的。
3、 eq_refmysql手冊是這樣說的:"對于每個來自于前面的表的行組合,從該表中讀取一行。這可能是最好的聯接類型,除了const類型。它用在一個索引的所有部分被聯接使用并且索引是UNIQUE或PRIMARY KEY"。eq_ref可以用于使用=比較帶索引的列。
4、 ref查詢條件索引既不是UNIQUE也不是PRIMARY KEY的情況。ref可用于=或<或>操作符的帶索引的列。
5、 ref_or_null該聯接類型如同ref,但是添加了MySQL可以專門搜索包含NULL值的行。在解決子查詢中經常使用該聯接類型的優化。
上面這五種情況都是很理想的索引使用情況。
6、 index_merge該聯接類型表示使用了索引合并優化方法。在這種情況下,key列包含了使用的索引的清單,key_len包含了使用的索引的最長的關鍵元素。
7、 unique_subquery該類型替換了下面形式的IN子查詢的ref: value IN (SELECT primary_key FROM single_table WHERE some_expr)unique_subquery是一個索引查找函數,可以完全替換子查詢,效率更高。
8、 index_subquery該聯接類型類似于unique_subquery??梢蕴鎿QIN子查詢,但只適合下列形式的子查詢中的非唯一索引: value IN (SELECT key_column FROM single_table WHERE some_expr)
9、 range只檢索給定范圍的行,使用一個索引來選擇行。
10、 index該聯接類型與ALL相同,除了只有索引樹被掃描。這通常比ALL快,因為索引文件通常比數據文件小。
11、 ALL對于每個來自于先前的表的行組合,進行完整的表掃描。(性能最差) B tree b+tree
指出MySQL能使用哪個索引在該表中找到行。
如果該列為NULL,說明沒有使用索引,可以對該列創建索引來提高性能。
顯示MySQL實際決定使用的鍵(索引)。如果沒有選擇索引,鍵是NULL。
可以強制使用索引或者忽略索引:
強制使用索引:USE%20INDEX(列名)
忽略使用索引:IGNORE%20INDEX(列名)
顯示MySQL決定使用的鍵長度。如果鍵是NULL,則長度為NULL。
注意:key_len是確定了MySQL將實際使用的索引長度。
顯示使用哪個列或常數與key一起從表中選擇行。
顯示MySQL認為它執行查詢時必須檢查的行數。
該列包含MySQL解決查詢的詳細信息
? Distinct:MySQL發現第1個匹配行后,停止為當前的行組合搜索更多的行。
? Not exists:MySQL能夠對查詢進行LEFTJOIN優化,發現1個匹配LEFT JOIN標準的行后,不再為前面的的行組合在該表內檢查更多的行。
? range checked for each record(index map: #):MySQL沒有發現好的可以使用的索引,但發現如果來自前面的表的列值已知,可能部分索引可以使用。
? Using filesort:MySQL需要額外的一次傳遞,以找出如何按排序順序檢索行。
? Using index:從只使用索引樹中的信息而不需要進一步搜索讀取實際的行來檢索表中的列信息。
? Using temporary:為了解決查詢,MySQL需要創建一個臨時表來容納結果。
? Using where:WHERE 子句用于限制哪一個行匹配下一個表或發送到客戶。
? Using sort_union(...), Usingunion(...), Using intersect(...):這些函數說明如何為index_merge聯接類型合并索引掃描。
? Using index for group-by:類似于訪問表的Usingindex方式,Usingindex for group-by表示MySQL發現了一個索引,可以用來查 詢GROUP BY或DISTINCT查詢的所有列,而不要額外搜索硬盤訪問實際的表。
索引可以提供查詢的速度,但并不是使用了帶有索引的字段查詢都會生效,有些情況下是不生效的,需要注意!
數據庫索引,是數據庫管理系統中一個排序的數據結構,以協助快速查詢、更新數據庫表中數據。索引的實現通常使用B樹(B-tree(多路搜索樹,并不是二叉的)是一種常見的數據結構)及其變種B+樹。
在數據之外,數據庫系統還維護著滿足特定查找算法的數據結構,這些數據結構以某種方式引用(指向)數據,這樣就可以在這些數據結構上實現高級查找算法。這種數據結構,就是索引。
為表設置索引要付出代價的:一是增加了數據庫的存儲空間,二是在插入和修改數據時要花費較多的時間(因為索引也要隨之變動)。
為什么使用索引就能加快查詢速度呢?
場景:面試官問你你有沒有做過數據庫優化啊?有做過,設計的時候給一些查詢字段加一些索引,為什么要加索引,為什么加了索引就快克?
索引就是通過事先排好序,從而在查找時可以應用二分查找等高效率的算法。
一般的順序查找,復雜度為O(n),而二分查找復雜度為O(log2n)。當n很大時,二者的效率相差及其懸殊。
舉個例子:
表中有一百萬條數據,需要在其中尋找一條特定id的數據。如果順序查找,平均需要查找50萬條數據。而用二分法,至多不超過20次就能找到。二者的效率差了2.5萬倍!
在使用LIKE關鍵字進行查詢的查詢語句中,如果匹配字符串的第一個字符為“%”,索引不起作用。只有“%”不在第一個位置,索引才會生效。

%20
MySQL可以為多個字段創建索引,一個索引可以包括16個字段。對于聯合索引,只有查詢條件中使用了這些字段中第一個字段時,索引才會生效。

查詢語句的查詢條件中只有OR關鍵字,且OR前后的兩個條件中的列都是索引時,索引才會生效,否則,索引不生效。
id是含有索引的
cid%20是有索引的
price%20是沒有索引的
MySQL從4.1版本開始支持子查詢,使用子查詢進行SELECT語句嵌套查詢,可以一次完成很多邏輯上需要多個步驟才能完成的SQL操作。
子查詢雖然很靈活,但是執行效率并不高。
那么問題又來了?。渴裁唇凶硬樵??為什么它效率不高?
(把內層查詢結果當作外層查詢的比較條件的)
%20 例子: %20select%20goods_id,goods_name%20from%20goods%20wheregoods_id%20=%20(select%20max(goods_id)%20from%20goods);
執行子查詢時,MYSQL需要創建臨時表,查詢完畢后再刪除這些臨時表,所以,子查詢的速度會受到一定的影響。這多了一個創建臨時表和銷毀表的過程啊。
優化方式:
可以使用連接查詢(JOIN)代替子查詢,連接查詢時不需要建立臨時表,其速度比子查詢快。
一個好的數據庫設計方案對于數據庫的性能往往會起到事半功倍的效果。這句話是什么意思呢,就是說我們的數據庫優化不僅僅要局限于查詢優化,要從這塊跳出來做好最開始的設計優化,如果你這個主要設計是不合理的這些個查詢優化效果也只是杯水車薪。
需要考慮數據冗余、查詢和更新的速度、字段的數據類型是否合理等多方面的內容。
對于字段較多的表,如果有些字段的使用頻率很低,可以將這些字段分離出來形成新表。
因為當一個表的數據量很大時,會由于使用頻率低的字段的存在而變慢。
項目實戰的時候會將一個完全信息的表里面的數據拆分出來形成多個新表 %20每個新表負責那一塊的數據查詢 %20然后這個拆分是定時的
對于需要經常聯合查詢的表,可以建立中間表以提高查詢效率。這個大家能不能理解?
通過建立中間表,將需要通過聯合查詢的數據插入到中間表中,然后將原來的聯合查詢改為對中間表的查詢。
舉個例子?。罕热缥覀冃枰谖鍙埍砝锩孀霾樵償祿?,left%20join%20每次查詢要連接五張表是吧 %20我這里做一個中間表 %20把查詢結果都放在這個中間表里面,只要在這個表里面查詢就行了啊
通常都是在統計當中有使用啊,每次統計報表的時候都是離線統計啊,后臺有有一個線程對你這統計結果查詢號放入一個中間表,然后你對這個中間表查詢就行了。
設計數據表時應盡量遵循范式理論的規約,盡可能的減少冗余字段,讓數據庫設計看起來精致、優雅。但是,合理的加入冗余字段可以提高查詢速度。
表的規范化程度越高,表和表之間的關系越多,需要連接查詢的情況也就越多,性能也就越差。
注意:
冗余字段的值在一個表中修改了,就要想辦法在其他表中更新,否則就會導致數據不一致的問題。
插入數據時,影響插入速度的主要是索引、唯一性校驗、一次插入的數據條數等。
為什么索引會影響插入速度呢?
索引越多,當你寫入數據的時候就會越慢,因為我們在插入數據的時候不只是把數據寫入文件,而且還要把這個數據寫到索引中,索引索引越多插入越慢
那么插入數據的優化,根據不同的存儲引擎優化手段不一樣,在MySQL中常用的存儲引擎有,MyISAM和InnoDB,兩者的區別:
http://www.cnblogs.com/panfeng412/archive/2011/08/16/2140364.html

對于非空表,插入記錄時,MySQL會根據表的索引對插入的記錄建立索引。如果插入大量數據,建立索引會降低插入數據速度。
為了解決這個問題,可以在批量插入數據之前禁用索引,數據插入完成后再開啟索引。
禁用索引的語句:
ALTERTABLE%20table_name%20DISABLE%20KEYS
開啟索引語句:
ALTERTABLE%20table_name%20ENABLE%20KEYS
對于空表批量插入數據,則不需要進行操作,因為MyISAM引擎的表是在導入數據后才建立索引。
唯一性校驗會降低插入記錄的速度,可以在插入記錄之前禁用唯一性檢查,插入數據完成后再開啟。
禁用唯一性檢查的語句:SET%20UNIQUE_CHECKS%20=%200;
開啟唯一性檢查的語句:SET%20UNIQUE_CHECKS%20=%201;
插入數據時,可以使用一條INSERT語句插入一條數據,也可以插入多條數據。

%20
第二種方式的插入速度比第一種方式快。
為什么?第一次執行兩條sql 第二次執行一條SQL
我們把sql語句發送到sql后要解析兩次 二第二次只需要解析一次啊
當需要批量導入數據時,使用LOAD%20DATA%20INFILE語句比INSERT語句插入速度快很多。
禁用唯一性檢查的語句:SET%20UNIQUE_CHECKS%20=%200;
開啟唯一性檢查的語句:SET%20UNIQUE_CHECKS%20=%201;
插入數據之前執行禁止對外鍵的檢查,數據插入完成后再恢復,可以提供插入速度。
禁用:SET%20foreign_key_checks%20=%200;
開啟:SET%20foreign_key_checks%20=%201;
插入數據之前執行禁止事務的自動提交,數據插入完成后再恢復,可以提高插入速度。
禁用:SET%20autocommit%20=%200;
開啟:SET%20autocommit%20=%201;
服務器的硬件性能直接決定著MySQL數據庫的性能,硬件的性能瓶頸,直接決定MySQL數據庫的運行速度和效率。
需要從以下幾個方面考慮:
1、 %20配置較大的內存。足夠大的內存,是提高MySQL數據庫性能的方法之一。內存的IO比硬盤快的多,可以增加系統的緩沖區容量,使數據在內存停留的時間更長,以減少磁盤的IO。
2、 %20配置高速磁盤,比如SSD。
3、 %20合理分配磁盤IO,把磁盤IO分散到多個設備上,以減少資源的競爭,提高并行操作能力。
4、 %20配置多核處理器,MySQL是多線程的數據庫,多處理器可以提高同時執行多個線程的能力。
通過優化MySQL的參數可以提高資源利用率,從而達到提高MySQL服務器性能的目的。
MySQL的配置參數都在my.conf或者my.ini文件的[mysqld]組中,常用的參數如下:
新聞熱點
疑難解答