1. 程式人生 > >淺談mysql配置優化和sql語句優化

淺談mysql配置優化和sql語句優化

    做優化,我在這裡引用淘寶系統分析師蔣江偉的一句話:只有勇於承擔,才能讓人有勇氣,有承擔自己的錯誤的勇氣。有承擔錯誤的勇氣,就有去做事得勇氣。無論做什麼事,只要是對的,就要去做,勇敢去做。出了錯誤,承擔錯誤,改正錯誤,這樣的人沒有人會去責怪。

    很久之前就想寫一篇關於mysql優化方面的文章了,忙於工作,在著也比較懶散。現在網上mysql優化方面的帖子很多,也不乏精品。很早聽一DBA前輩說過:mysql的優化,三分配置的優化,七分sql語句的優化。之前不是很理解,但接觸到高併發大資料的時候,這句話的含義尤為突出,甚至可以說一分配置的優化,九分語句的優化。

mysql的優化,一般分為配置的優化、

sql語句的優化、表結構的優化、索引的優化,這裡著重說前兩點。

一、配置的優化

    配置的優化其實包含兩個方面的:作業系統核心的優化和mysql配置檔案的優化

    1、系統核心的優化對專用的mysql伺服器來說,無非是記憶體實用、連線數、超時處理、TCP處理等方面的優化,根據自己的硬體配置來進行優化,這裡不多講;

    2mysql配置的優化,一般來說包含:IO處理的常用引數、最大連線數設定、快取使用引數的設定、慢日誌的引數的設定、innodb相關引數的設定等,如果有主從關係在設定主從同步的相關引數即可,網上的相關配置檔案很多,大同小異,常用的設定大多修改這些差不多就夠用了。

以下是我的一個mysql配置檔案,僅供參考:

###############################################

[mysqld]

skip-name-resolve

server-id = 1

bind-address = 0.0.0.0

port = 3306

datadir = /home/mysql

tmpdir = /tmp

default_storage_engine = InnoDB

character_set_server = utf8

innodb_file_per_table = 1

innodb_log_file_size = 512M

innodb_log_files_in_group = 4

innodb_rollback_on_timeout = 1

slow_query_log = 1

slow_query_log_file =/var/log/mysql/mysql-slow.log

long_query_time = 1

#log-queries-not-using-indexes#這個引數不安全,說是記錄沒有用到索引的語句,其實記錄的全部的日誌,佔用大量的IO,建議不要開啟

#relay_log_recovery=1#這個引數在叢庫上一定要加上

query_cache_type = off

query_cache_size = 0

#這兩項是禁用快取,這個使伺服器用途而定:寫比較多的資料庫最好禁用,因為沒寫一次他要修改快取中的資料,給資料庫帶來額外的開銷,讀比較的可以開啟,可以提高查詢效率

#一下4個引數是mysql5.6上的新特性

innodb_buffer_pool_dump_at_shutdown = 1 #解釋:在關閉時把熱資料dump到本地磁碟。

innodb_buffer_pool_dump_now = 1 #解釋:採用手工方式把熱資料dump到本地磁碟。

innodb_buffer_pool_load_at_startup = 1 #解釋:在啟動時把熱資料載入到記憶體。

innodb_buffer_pool_load_now = 1 #解釋:採用手工方式把熱資料載入到記憶體。

read_buffer_size = 2M

sort_buffer_size = 2M

join_buffer_size = 1M

key_buffer_size = 2G 

thread_cache_size = 2048

open_files_limit=65535

innodb_open_files = 8192

max_allowed_packet = 64M

thread_stack = 512k

max_length_for_sort_data = 16k

tmp_table_size = 1G

max_heap_table_size = 1G

max_connections = 4000      

max_connect_errors = 30000

innodb_read_io_threads = 8

innodb_write_io_threads = 16

innodb_flush_method = O_DIRECT

innodb_io_capacity = 20000#根據硬碟的情況修改,stat的用100sas200sasriad10的為400fision-io的可以設定為20000

innodb_buffer_pool_size = 72G#記憶體的80%

innodb_buffer_pool_instances=18

thread_concurrency=0

innodb_thread_concurrency = 0

innodb_log_buffer_size = 16M

innodb_flush_log_at_trx_commit = 2

innodb_lock_wait_timeout = 60

innodb_old_blocks_time=1000

innodb_use_native_aio = 1

innodb_purge_threads=1

innodb_change_buffering=inserts

##############################################

二、sql語句的優化

    前期的配置優化做完,其實在很長的一段時間內,基本上不用在去優化了。而一條sql使用不當,致使整個資料庫故障的情況相信做DBA的經常遇到。所以,sql語句的優化和稽核才是每個DBA的重中之重。

sql語句的優化,一般的基本原則有以下幾個方面:

1、儘量稍作計算

Mysql的作用是用來存取資料的,不是做計算的,做計算的話可以用其他方法去實現,mysql做計算是很耗資源的。

2.儘量少 join

MySQL 的優勢在於簡單,但這在某些方面其實也是其劣勢。MySQL 優化器效率高,但是由於其統計資訊的量有限,優化器工作過程出現偏差的可能性也就更多。對於複雜的多表 Join,一方面由於其優化器受限,再者在 Join 這方面所下的功夫還不夠,所以效能表現離 Oracle 等關係型資料庫前輩還是有一定距離。但如果是簡單的單表查詢,這一差距就會極小甚至在有些場景下要優於這些資料庫前輩。

3.儘量少排序

  排序操作會消耗較多的 CPU 資源,所以減少排序可以在快取命中率高等 IO 能力足夠的場景下會較大影響 SQL 的響應時間。

  對於MySQL來說,減少排序有多種辦法,比如:

  通過利用索引來排序的方式進行優化

  減少參與排序的記錄條數

  非必要不對資料進行排序

4.儘量避免 select *

  在資料量少並且訪問量不大的情況下,select * 沒有什麼影響,但是量級達到一定級別的時候,在執行效率和IO資源的使用上,還是有很大關係的,用什麼欄位取什麼欄位,減少不必要的資源浪費。

    之前遇到過因為一個欄位儲存的資料比較大,併發高的情況下把網路頻寬跑滿的情況,造成網站打不開或是開啟速度極慢的情況。

5.儘量用 join 代替子查詢

  雖然 Join 效能並不佳,但是和 MySQL 的子查詢比起來還是有非常大的效能優勢。MySQL 的子查詢執行計劃一直存在較大的問題,雖然這個問題已經存在多年,但是到目前已經發布的所有穩定版本中都普遍存在,一直沒有太大改善。雖然官方也在很早就承認這一問題,並且承諾儘快解決,但是至少到目前為止我們還沒有看到哪一個版本較好的解決了這一問題。

6.儘量少 or

  當 where 子句中存在多個條件以“或”並存的時候,MySQL 的優化器並沒有很好的解決其執行計劃優化問題,再加上 MySQL 特有的 SQL Storage 分層架構方式,造成了其效能比較低下,很多時候使用 union all 或者是union(必要的時候)的方式來代替“or”會得到更好的效果。

7.儘量用 union all 代替 union

union  union all 的差異主要是前者需要將兩個(或者多個)結果集合並後再進行唯一性過濾操作,這就會涉及到排序,增加大量的 CPU 運算,加大資源消耗及延遲。所以當我們可以確認不可能出現重複結果集或者不在乎重複結果集的時候,儘量使用 union all 而不是 union

8.儘量早過濾

  這一優化策略其實最常見於索引的優化設計中(將過濾性更好的欄位放得更靠前)

  在 SQL 編寫中同樣可以使用這一原則來優化一些 Join  SQL。比如我們在多個表進行分頁資料查詢的時候,我們最好是能夠在一個表上先過濾好資料分好頁,然後再用分好頁的結果集與另外的表 Join,這樣可以儘可能多的減少不必要的 IO 操作,大大節省 IO 操作所消耗的時間。

9.避免型別轉換

  這裡所說的“型別轉換”是指 where 子句中出現 column 欄位的型別和傳入的引數型別不一致的時候發生的型別轉換:

A:人為在column_name 上通過轉換函式進行轉換

  直接導致 MySQL(實際上其他資料庫也會有同樣的問題)無法使用索引,如果非要轉換,應該在傳入的引數上進行轉換

B:由資料庫自己進行轉換

  如果我們傳入的資料型別和欄位型別不一致,同時我們又沒有做任何型別轉換處理,MySQL 可能會自己對我們的資料進行型別轉換操作,也可能不進行處理而交由儲存引擎去處理,這樣一來,就會出現索引無法使用的情況而造成執行計劃問題。

    以上兩種情況在開發者因為某種原因經常會有,本來可以用到索引的結果型別不對沒有用到索引,或是因為型別不對又有越界的情況發生造成無法使用索引的情況,結果造成很嚴重的事故。

10.優先優化高併發的 SQL,而不是執行頻率低某些“大”SQL

  對於破壞性來說,高併發的 SQL 總是會比低頻率的來得大,因為高併發的 SQL 一旦出現問題,甚至不會給我們任何喘息的機會就會將系統壓跨。而對於一些雖然需要消耗大量 IO 而且響應很慢的 SQL,由於頻率低,即使遇到,最多就是讓整個系統響應慢一點,但至少可能撐一會兒,讓我們有緩衝的機會。

11.從全域性出發優化,而不是片面調整

SQL 優化不能是單獨針對某一個進行,而應充分考慮系統中所有的 SQL,尤其是在通過調整索引優化 SQL 的執行計劃的時候,千萬不能顧此失彼,因小失大。

12.儘可能對每一條執行在資料庫中的SQL進行 explain

優化 SQL,需要做到心中有數,知道SQL 的執行計劃才能判斷是否有優化餘地,才能判斷是否存在執行計劃問題。在對資料庫中執行的 SQL進行了一段時間的優化之後,很明顯的問題 SQL 可能已經很少了,大多都需要去發掘,這時候就需要進行大量的 explain 操作收集執行計劃,並判斷是否需要進行優化。

題外話:很多剛接觸mysql的朋友問,有什麼mysql專業書籍推薦?我推薦《MySQL高效能》第三版,是mysql 領域的經典之作,擁有廣泛的影響力,涵蓋的知識面也比較面,一本在手,基礎知識無憂,其他需要在實戰中積累經驗了,本人也是此書的受益者。

相關推薦

mysql配置優化sql語句優化

    做優化,我在這裡引用淘寶系統分析師蔣江偉的一句話:只有勇於承擔,才能讓人有勇氣,有承擔自己的錯誤的勇氣。有承擔錯誤的勇氣,就有去做事得勇氣。無論做什麼事,只要是對的,就要去做,勇敢去做。出了錯誤,承擔錯誤,改正錯誤,這樣的人沒有人會去責怪。     很久之前就想

mysql優化sql語句優化總結

結構 沒有 sele 大量 unsigned 他還 判斷 pla 可能 mysql性能優化 1、 EXPLAIN 你的 SELECT 查詢。使用 EXPLAIN 關鍵字可以讓你知道MySQL是如何處理你的SQL語句的。這可以幫你分析你的查詢語句或是表結構的性能瓶頸。 2、為

Mysql中wherehaving的區別

where和having的區別一、誤區:不要錯誤的認為having和group by 必須配合使用.二、where和having用法解析:1、 where和having都可以使用的場景: select goods_price,goods_name from goods where goods_price &g

MySQL(二) —— MySQL效能優化SQL語句優化

          SQL語句優化   MySQL優化的目的   1、避免出現頁面訪問錯誤:或由於資料庫連線超時 timeout 產生頁面5xx錯誤;或由於慢查詢造成頁面無法載入;或由於阻        塞造成資料無法提交;

MySQL(二) —— MySQL效能優化SQL語句優化

          SQL語句優化 MySQL優化的目的   1、避免出現頁面訪問錯誤:或由於資料庫連線超時 timeout 產生頁面5xx錯誤;或由於慢查詢造成頁面無法載入;或由於阻        塞造成資料無法提交;   2、增加資料庫的穩定性:避免由於低效查詢

mysql資料庫優化大全--sql語句優化大全

一,SQL語句效能優化 1, 對查詢進行優化,應儘量避免全表掃描,首先應考慮在 where 及 order by 涉及的列上建立索 引。 2,應儘量避免在 where 子句中對欄位進行 null 值判斷,建立表時NULL是預設值,但大多數時候 應該使用NOT N

mysql的鎖索引之間莫大的聯絡

  在平時我們用mysql的鎖時,一般剛接觸資料庫是很少考慮鎖的效率,一般只求到達防止併發的目的就可以了,但是隨著資料量的增大我們就會發現有很多sql我們已經寫的非常優化了,但是有時候還是很慢,很難找到原因,這時候我們就應該考慮一下是不是mysql的鎖在導致的,(當然可能的

1.4 資料庫常用SQL語句(正文)——MySQL資料庫命令SQL語句

前面我們已經講述了,登入時,我們使用mysql –u root –p命令進行,此時如果設定了密碼,則需要輸入密碼。 輸入密碼後即進入MySQL的操作介面,此時,命令列窗體左側顯示“mysql>”表示此時可接受mysql命令。 (1)列出全部資料庫命令 我們使用“show databases;”命令列

數據庫性能優化SQL語句優化(轉 java知音)

可能 資源 詳細介紹 有助於 效果 這就是 詳細 分組統計 完全 一、問題的提出 在應用系統開發初期,由於開發數據庫數據比較少,對於查詢SQL語句,復雜視圖的編寫等體會不出SQL語句各種寫法的性能優劣,但是如果將應用系統提交實際應用後,隨著數據庫中數據的增加,系統的

數據庫優化SQL語句優化-記錄

得到 顯式 重要 adding sys 狀態 檢驗 發現 最大數 1. 操作符優化 (a) IN 操作符 從Oracle執行的步驟來分析用IN的SQL與不用IN的SQL有以下區別: ORACLE試圖將其轉換成多個表的連接,如果轉換不成功則先執行IN裏面的子查詢,再查詢外層的

資料庫效能優化SQL語句優化

避免使用HAVING子句, HAVING 只會在檢索出所有記錄之後才對結果集進行過濾. 這個處理需要排序,總計等操作. 如果能通過WHERE子句限制記錄的數目,那就能減少這方面的開銷. (非oracle中)on、where、having這三個都可以加條件的子句中,on是最先執行,where次之,having最

資料庫效能優化SQL語句優化1

一、問題的提出 在應用系統開發初期,由於開發資料庫資料比較少,對於查詢SQL語句,複雜檢視的的編寫等體會不出SQL語句各種寫法的效能優劣,但是如果將應用系統提交實際應用後,隨著資料庫中資料的增加,系統的響應速度就成為目前系統需要解決的最主要的問題之一。系統優化中一個很重要的方面就是SQL語句的優化。對於

MySQL優化sql語句查詢常用的30種方法

系統資源 all 數據量過大 連續 don 問題 not sele 客戶端 1.對查詢進行優化,應盡量避免全表掃描,首先應考慮在 where 及 order by 涉及的列上建立索引。 2.應盡量避免在 where 子句中使用!=或<>操作符,否則將引擎放棄使用

MySQL優化 SQL 語句查詢常用的 30 種方法

個數 尋找 情況 don union all 子句 set 其他 算術 1、對查詢進行優化,應盡量避免全表掃描,首先應考慮在 where 及 order by 涉及的列上建立索引。 2、應盡量避免在 where 子句中使用!=或<>操作符,否則將引擎放棄使用索引

013-- mysql常用的查詢優化方法 MySQL優化sql語句查詢常用的30種方法

淺談MySQL中優化sql語句查詢常用的30種方法   1.對查詢進行優化,應儘量避免全表掃描,首先應考慮在 where 及 order by 涉及的列上建立索引。 2.應儘量避免在 where 子句中使用!=或<>操作符,否則將引擎放棄使用索引而進行全

MySQL優化sql語句查詢常用的30種方法(sql優化)

1.對查詢進行優化,應儘量避免全表掃描,首先應考慮在 where 及 order by 涉及的列上建立索引。  2.應

SQL語句優化

一、操作符優化   1、IN 操作符      用IN寫出來的SQL的優點是比較容易寫及清晰易懂,這比較適合現代軟體開發的風格。但是用IN的SQL效能總是比較低的,從Oracle執行的步驟來分析用IN的SQL與不用IN的SQL有以下區別:     ORACLE試圖將其轉換成

MySQL SQL優化

本文首發於個人微信公眾號《andyqian》,期待你的關注! 前言 有好幾天沒有寫文章了,實在不好意思。之前就有朋友希望我寫寫MySQL優化的文章。我遲遲沒有動筆,主要是因為,SQL優化這個東西,很廣,技巧也很多。自己在SQL優化方面的知識又還很欠缺。總覺得還不到分享的。

mysql 如何查看sql語句執行時間效率

訪問 執行時間 subquery ber 如果 pan from xtra 重要 查看執行時間 1 show profiles; 2 show variables;查看profiling 是否是on狀態; 3 如果是off,則 set profiling = 1; 4 執

mysql sql優化sql執行計劃

mysql 執行計劃SQL優化禁用SELECT *使用SELECT COUNT(*) 統計行數盡量少運算盡量避免全表掃描,如果可以,在過濾列建立索引盡量避免在WHERE子句對字段進行NULL判斷盡量避免在WHERE子句使用!= 或者<>盡量避免在WHERE子句使用OR連接盡量避免對字段進行表達式計