天天看點

大廠都在用的MySQL優化方案(中)3 explain分析SQL的執行計劃4 簡單的優化方法存儲過程與觸發器的差別面試回答資料庫優化問題從以下幾個層面入手

3 explain分析SQL的執行計劃

4 簡單的優化方法

分析和存儲表的關鍵字分布

分析的結果可以使得系統得到準确的統計資訊使得sql,能夠生成正确的執行計劃。如果使用者感覺實際執行計劃并不預期的執行計劃,執行一次分析表可能會解決問題

mysql> analyze table payments;      
大廠都在用的MySQL優化方案(中)3 explain分析SQL的執行計劃4 簡單的優化方法存儲過程與觸發器的差別面試回答資料庫優化問題從以下幾個層面入手

檢查表

檢查一個表或多個表是否有錯誤,也可以檢查視圖是否錯誤

check table payment;      
大廠都在用的MySQL優化方案(中)3 explain分析SQL的執行計劃4 簡單的優化方法存儲過程與觸發器的差別面試回答資料庫優化問題從以下幾個層面入手

優化表

如果删除了表的一大部分,或者如果已經對可變長度的行表(含varchar、blob、text列)的表進行改動,則使用optimize 進行表優化,這個指令可以使表中的空間碎片進行合并、并且可以消除由于删除或者更新造成的空間浪費

optimize table payment;      

對于innodb引擎的表,可以通過設定innodb_file_per_taable參數,設定InnoDb為獨立表空間模式,這樣每個資料庫的每個表都會生成一個獨立的idb檔案,用于存儲表的資料和索引,可以一定程度減少Innodb表的空間回收問題,另外,在删除大量資料後,Innodb表可以通過alter table但是不鏽鋼引擎方式來回收不用的空間

alter table payment enigine=innodb;      

ANALYZE,CHECK,OPTIMIZE,ALTER TABLE執行期間都是對表進行鎖定,是以要在資料庫不頻繁的時候執行相關的操作

拆分表

分區将資料在實體上分隔開,不同分區的資料可以制定儲存在處于不同磁盤上的資料檔案裡。

這樣,當對這個表進行查詢時,隻需要在表分區中進行掃描,而不必進行全表掃描,明顯縮短了查詢時間,

另外處于不同磁盤的分區也将對這個表的資料傳輸分散在不同的磁盤I/O,一個精心設定的分區可以将資料傳輸對磁盤I/O競争均勻地分散開。

對資料量大的時時表可采取此方法。可按月自動建表分區。

存儲過程與觸發器的差別

兩者唯一的差別是觸發器不能用EXECUTE語句調用,而是在使用者執行Transact-SQL語句時自動觸發(激活)執行。

觸發器是在一個修改了指定表中的資料時執行的存儲過程。

通常通過建立觸發器來強制實作不同表中的邏輯相關資料的引用完整性和一緻性。

觸發器不同于存儲過程,觸發器主要是通過事件執行觸發而被執行的,

存儲過程可以通過存儲過程名稱名字而直接調用。

當對某一表進行諸如UPDATE、INSERT、DELETE這些操作時,SQLSERVER就會自動執行觸發器所定義的SQL語句,進而確定對資料的處理必須符合這些SQL語句所定義的規則。

面試回答資料庫優化問題從以下幾個層面入手

(1)、根據服務層面:配置mysql性能優化參數;

(2)、從系統層面增強mysql的性能:優化資料表結構、字段類型、字段索引、分表,分庫、讀寫分離等等。

(3)、從資料庫層面增強性能:優化SQL語句,合理使用字段索引。

(4)、從代碼層面增強性能:使用緩存和NoSQL資料庫方式存儲,如MongoDB/Memcached/Redis來緩解高并發下資料庫查詢的壓力。

(5)、減少資料庫操作次數,盡量使用資料庫通路驅動的批處理方法。

(6)、不常使用的資料遷移備份,避免每次都在海量資料中去檢索。

(7)、提升資料庫伺服器硬體配置,或者搭建資料庫叢集。

(8)、程式設計手段防止SQL注入:使用JDBC PreparedStatement按位插入或查詢;正規表達式過濾(非法字元串過濾);

大批量的插入資料

當用load導入資料,适當的設定可以提供導入的速度

對于MyISAM存儲引擎的表,可以通過以下方式快速導入大量的資料

alter table tab_name disable keys;
loading the data
alter table tab_name disable keys;      

disable keys和enable keys 用來打開或者關閉MyISAM表非索引的更新。在導入大量的資料到一個非空的MyISAM表,通過設定這兩個指令,可以提高導入的效率

對于Innodb類型的表不能使用上面的方式提高導入效率

因為Innodb類型的表是按照主鍵的順序儲存,所有将導入的資料按照主鍵的順序排序,可以有效地提高導入資料的效率

在導入資料強執行SET UNIQUE_CHECKS=0,關閉唯一性校驗,在導入結束後執行SET UNIQUE_CHECKS=1.恢複唯一性校驗,可以提高導入的效率,如果應用使用自動送出的方式,建議在導入前執行SET AUTOCOMMIT=0時,關閉自動送出,導入結束後再執行SET AUTOCOMMIT=1,打開自動送出,也可以提高導入的效率

優化insert語句

  • 如果同時從一個用戶端插入很多行,應盡量使用多個值表的insert語句,這種方式将大大縮減用戶端與資料庫之間的連接配接、關閉等消耗,使得效率比分開執行的單個insert語句快(大部分情況下,使用多個值表的insert語句那比單個insert語句快上好幾倍)。
insert into test values(1,2),(1,3)...      

如果從不同客戶插入很多行,可以通過使用insert delayed語句提高更高的速度,delayed的含義是讓insert語句馬上執行,其實資料都被放到記憶體的隊列中,并沒有真正寫入磁盤,這比每條語句分别插入要快的多;LOW_PRIORITY剛好相反,在所有其他使用者對表的讀寫完成後才可以進行

将索引檔案和資料檔案分在不同的磁盤上存放(利用建表中的選項)

如果進行批量插入,可以通過增加bulk_insert_buffer_size變量值的方法來通過速度,但是,這隻能對MyISAM表使用。

當從一個文本檔案裝載一個表時,使用LOAD DATA INFILE。這通常比使用很多INSERT語句塊快20倍

優化ORDER BY語句

  • 第一種通過有序排序索引順序掃描,這種方式在使用explain分析查詢的時候顯示為Using Index,不需要額外的排序,操作效率較高-innodb引擎
大廠都在用的MySQL優化方案(中)3 explain分析SQL的執行計劃4 簡單的優化方法存儲過程與觸發器的差別面試回答資料庫優化問題從以下幾個層面入手
explain select customer_id from customer order by store_id;      
大廠都在用的MySQL優化方案(中)3 explain分析SQL的執行計劃4 簡單的優化方法存儲過程與觸發器的差別面試回答資料庫優化問題從以下幾個層面入手
大廠都在用的MySQL優化方案(中)3 explain分析SQL的執行計劃4 簡單的優化方法存儲過程與觸發器的差別面試回答資料庫優化問題從以下幾個層面入手

第二張通過傳回資料進行排序,也就是通常說的Filesort排序,所有不是通過索引直接傳回排序結果的排序豆角Filesort排序。Filesort并不代表通過磁盤檔案進行排序,而隻是說明進行了一個排序操作,至于排序操作是否進行了磁盤檔案或臨時表等,則取決于MySql伺服器對排序參數的設定和需要排序資料的大小-myshim引擎

explain select * from customer order by store_id;      

Filesort是通過相應的排序算法,将取得的資料在sort_buffer_size系統變量設定的記憶體排序區進行排序,如果記憶體裝載不下,它會将磁盤上的資料進行分塊,再對各個資料塊進行排序,然後将各個塊合并成有序的結果集。sort_buffer_size設定的排序區是每個線程獨占的,所有同一個時刻,MySql存在多個sort buffer排序區

優化group by 語句

如果查詢包括group by 但使用者想要避免排序結果的消耗,可以指定group by null

優化嵌套查詢

子查詢可以被更有效率的連接配接替代

explain select * from customer where customer_id not in(select customer_id from payment)

explain select * from customer a left join payment b on a.customer_id=b.customer_id where b.customer id is null      

連接配接之所用更有效率是因為mysql不需要在記憶體中建立臨時表來完成這個邏輯上需要兩個步驟的查詢工作

優化分頁查詢

一般分頁查詢,通過建立覆寫索引能夠比較好地提高性能。一個場景是"limit 1000,20",此時Mysql排序出前1020條資料後僅僅需要傳回第1001到1020條記錄,前1000條資料都被抛棄,查詢和排序代價非常高

優化方式:可以增加一個字段last_page_record.記錄上一頁和最後一頁的編号,通過

explain select ...where last_page_record<... desc limt ..      

如果排序字段出現大量重複字段,不适用這種方式進行優化