MySQL 數據庫 - SQL 優化

一.結構圖
MySQL 數據庫 - SQL 優化
在這裏插入圖片描述
1.1ISAM(Indexed Sequential Access Method)
ISAM是一個定義明確且定義明確的數據表格管理方法,在設計時就考慮到數據庫的查詢次數遠遠大於更新的次數。因此,ISAM執行讀取操作的速度很快,而且不佔用大量的內存和存儲資源。
ISAM的兩個不足點:
1.ISAM不支持事務;
2.不能夠容錯。如果你的硬盤崩潰了,那麼數據文件就無法恢復;
如果你正在把ISAM用在關鍵的應用程序裏面,那麼必須經常備份你所有的實時數據,通過其複製特性,MYSQL能夠支持這樣的備份應用程序

使用 ISAM 注意點:必須經常備份所有實時數據。

1.2MyISAM
MyISAM是MYSQL的ISAM拓展格式數據引擎。除了提供ISAM裏面所沒有的索引和字段管理的大量功能,MyISAM還使用一種表格鎖定的機制,來優化多個併發的讀寫操作,其代價是要經常運行OPTIMIZE TABLE 命令;來回覆被更新機制浪費的空間。MyISAM還有一些有用的拓展,例如用來修復數據庫文件的MyISAMCHK 工具和用來恢復浪費空間的 MyISAMPACK 工具。MYISAM 強掉了快速讀取操作,這可能就是爲什麼MYSQL受到WEB開發如此青睞的主要原因:在WEB開發中所進行的大量數據操作都是讀取操作。所以,大多數虛擬主機供應商的INTERNET 平臺提供商 只允許使用 MYISAM 格式。
MyISAM 格式的一個重要缺陷就是不能在表損壞後恢復數據。
MyISAM引擎使用注意事項:必須經常使用Optimize Table 命令清理空間;必須經常備份所有實時數據。工具有用來工具有用來修復數據庫文件的 MyISAMCHK 工具和用來恢復浪費空間的 MyISAMPACK 工具。不支持事務。數據越多,寫操作效率越低。因爲要維護數據和索引信息。(索引越多,相對效率越低)
如果使用該數據庫引擎,會生成三個文件:
.frm:表結構信息
.MYD:數據文件
.MYI:表的索引信息

1.3InnoDB
InnoDB數據庫引擎都是早就MYSQL靈活性的技術的直接產品,這些技術就是MYSQL++API。在使用MYSQL的時候,你面對的沒一個挑戰幾乎都源於ISAM和MyISAM數據庫引擎不支持事務處理也不支持外鍵。儘管要比ISAM和MyISAM引擎慢很多,但是InnoDB包括了對事務和外鍵的支持,這兩點都是前兩個引擎所沒有的。到現在的MYSQL(5.5以上版本)常用版本默認引擎。

InnoDB 給 MySQL 提供了具有提交、回滾和崩 潰恢復能力的事務安全(ACID 兼容)存儲引擎。InnoDB 鎖定在行級並且也在 SELECT 語句提 供一個 Oracle 風格一致的非鎖定讀,這些特色增加了多用戶部署的性能。沒有在 InnoDB 中 擴大鎖定的需要,因爲在 InnoDB 中行級鎖定適合非常小的空間。InnoDB 也支持 FOREIGN KEY 強制。在 SQL 查詢中,你可以自由地將 InnoDB 類型的表與其它 MySQL 的表的類型混合起來,甚至在同一個查詢中也可以混合。 InnoDB 是爲處理巨大數據量時的最大性能設計,它的 CPU 效率可能是任何其它基於 磁盤的關係數據庫引擎所不能匹敵的。 InnoDB 存儲引擎被完全與 MySQL 服務器整合,InnoDB 存儲引擎爲在主內存中緩存數據 和索引而維持它自己的緩衝池。InnoDB 存儲它的表&索引在一個表空間中,表空間可以包 含數個文件(或原始磁盤分區)。這與 MyISAM 表不同,比如在 MyISAM 表中每個表被存在 分離的文件中。InnoDB 表可以是任何尺寸,即使在文件尺寸被限制爲 2GB 的操作系統上。 在 MySQL5.7 版本中,InnoDB 存儲引擎管理的數據文件爲兩個:分別是 frm,idb 文件。
InnoDB 特點:
1)、支持事務
2)、數據多版本讀取(InnoDB+MyISAM+ISAM)
3)、鎖定機制的改進
4)、實現外鍵

二.innodb 與 myisam 區別

1.. InnoDB 支持事務,MyISAM 不支持,對於InnoDB每一條SQL語句都默認封裝成事務,自動提交
這樣會影響速度,所以最好把多條SQL語句放在begin transaction和commit之間組成一個事務
2.. InnoDB 支持外鍵,而 MyISAM 不支持。對一個包含外鍵的 InnoDB 錶轉爲 MYISAM  失敗;
3.InnoDB是聚集索引,數據文件和索引綁定在一起,必須要有主鍵,通過主鍵索引效率很高。但是輔
助索引需要查詢兩次,先查詢主鍵,然後 通過主鍵查詢到數據。因此,主鍵不應該過大,因爲主鍵過
大,其他的索引也會很大。
而MyISAM是非聚集索引,數據文件是分離的,索引保存的是數據文件的指針。主鍵索引和輔助索引是
獨立的
4.InnoDB不保存表的具體行數,執行select * from table需要進行全局掃描;
MyISAM用一個變量保存了整個表的行數,執行上述語句只需讀出該變量即可,速度很快
5.. Innodb 不支持全文索引,而 MyISAM 支持全文索引,查詢效率上 MyISAM 要高;

2.1如何選擇數據庫索引
1.是否支持事務?需要選擇InnoDB,不需要選擇MyISAM;
2.如果表中絕大多數只是讀查詢,可以考慮MyISAM,如果讀寫也挺頻繁,使用InnoDB;
3.系統崩潰後,MyISAM恢復困難,能否接受;
4.MYSQL5.5版本之後。InnoDB已經成爲了mysql的默認引擎,說明優勢有目共睹,不知道用那個引擎,那就用InnoDB,至少不會差;

三.MYSQL中索引的簡介
3.1索引的優點
爲什麼要創建索引? 因爲創建索引可以大大提高系統的查詢性能
第一.創建唯一索引,可以保證數據庫表中每一行數據的唯一性;
第二.可以大大加快數據的檢索速度,這也是創建索引的主要原因;
第三.可以加快表與表之間的連接,特別是實現數據的參考方面有特別的意義;
第四.在使用分組和排序字句進行數據檢索時,可以減少查詢中分組和排序的時間;
第五:通過使用索引,可以在查詢的過程中,使用查詢優化器,提高系統的性能;

3.2索引的缺點
第一:創建索引和維護索引要消耗時間,這種時間隨數據量的增加而增加;
第二:索引佔用物理空間,除了數據表佔據空間外,每個索引還要佔用一定的物理空間。如果要簡歷聚集索引,那麼需要的空間更大
第三:對錶中的數據進行增加,刪除和修改的時候,索引也要動態的維護,這樣就降低了數據的維護速度:

3.3什麼樣的字段適合創建索引?
第一:在需要搜索的列上,可以加快搜索速度;
第二:在作爲主鍵的列上,強制改列的唯一性和組織表中數據的排列數據;
第三:在經常用在連接的列上,這些列是一些外鍵,可以加快連接的速度;
第四:在經常需要根據範圍進行搜索的列上創建索引,因爲索引已經排序,其指定的範圍是連續的
第五:在經常需要排序的列上建立索引,因爲索引已經排序,這樣查詢可以利用索引的排序,加快排序查詢時間;
第六:在經常使用WHERE子句中的列上創建索引,加快條件的判斷速度;

3.4什麼樣的字段不適合建立索引?
第一:在查詢中很少使用或者列不應該創建索引;
第二;只有很少數據值的列不應該增加索引;
第三:哪些定義text,image,和bit數據類型的列不應該增加索引;
第四:當修改性能遠遠大於檢索性能時,不應該創建索引;

四.MYSQL中的索引種類
4.1 B-Tree索引
B-Tree索引,就是所有的索引節點按照balance tree的數據結構來存儲。B-Tree結構可以顯著減少定位記錄時所經歷的中間過程,從而加快存取速度。
B-Tree中,每個節點包含:
1.本節點所含關鍵字的個數;
2.指向父節點的字數;
3.關鍵字;
4.指向節點的指針;
對於一棵 m 階 B-tree,每個結點至多可以擁有 m 個子結點。各結點的關鍵字和可以擁 有的子結點數都有限制,規定 m 階 B-tree 中,根結點至少有 2 個子結點,除非根結點爲葉 子節點,相應的,根結點中關鍵字的個數爲 1~m-1;非根結點至少有[m/2]([],向上取整) 個子結點,相應的,關鍵字個數爲[m/2]-1~m-1

B-tree有以下特徵:
1.關鍵字集合分佈式在整棵樹中;
2.任何一個關鍵字出現且出現在一個節點中;
3.搜索有可能在非葉子節點結束;
4.搜索性能等價於在關鍵字全集內做一次二分查找;
5.自動層次控制;
由於限制了除根結點以外的非葉子結點,至少含有 M/2 個兒子,確保了結點的至少利 用率,其最低搜索性能爲:
在這裏插入圖片描述
其中,M 爲設定的非葉子結點最多子樹個數,N 爲關鍵字總數; 所以 B-樹的性能總是等價於二分查找(與 M 值無關),也就沒有 B 樹平衡的問題; 由於 M/2 的限制,在插入結點時,如果結點已滿,需要將結點分裂爲兩個各佔 M/2 的 結點;刪除結點時,需將兩個不足 M/2 的兄弟結點合併。

MYSQL中索引管理
在 MySQL 中,對索引的查看和刪除操作是所有索引類型通用的。
1.普通索引
這是最基本的索引,它沒有任何限制 MyIASM 中默認的 BTREE 類型的索引,也是我們大 多數情況下用到的索引。
2.唯一索引
與普通索引類似,不同的是:索引列的值必須爲一,但允許有空值。如果是組合索引,則值的組合必須唯一,創建方法和普通索引類似;
3.全文索引
MySQL 從 3.23.23 版開始支持全文索引和全文檢索,FULLTEXT 索引僅可用於 MyISAM 表;他們可以從 CHAR、VARCHAR 或 TEXT 列中作爲 CREATE TABLE 語句的一部分被創建,或 是隨後使用 ALTER TABLE 或 CREATE INDEX 被添加。 對於較大的數據集,將你的資料輸入一個沒有 FULLTEXT 索引的表中,然後創建索引, 其速度比把資料輸入現有 FULLTEXT 索引的速度更爲快。不過切記對於大容量的數據表,生 成全文索引是一個非常消耗時間非常消耗硬盤空間的做法。
4.組合索引
平時用的 SQL 查詢語句一般都有比較多的限制條件,所以爲了進一步榨取 MySQL 的效 率,就要考慮建立組合索引。例如上表中針對 title 和 time 建立一個組合索引:ALTER TABLE article ADD INDEX index_title_time (title(50),time(10))。建立這樣的組合索引,其實是相當於分 別建立了下面兩組組合索引: –title,time –title 爲什麼沒有 time 這樣的組合索引呢?這是因爲 MySQL 組合索引“最左前綴”的結果。簡 單的理解就是隻從最左面的開始組合。並不是只要包含這兩列的查詢都會用到該組合索引,

五.MYSQL中索引的優化
1.索引不會包含有NUll值的列
只要列中包含有NUll值都將不會被包含在索引中,組合索引中只要有一列含有NUll,那麼這一列對於此組合索引是無效的。所以我們在數據庫設計的時候不要讓字段的默認值爲NUll;
2.使用短索引
對串列進行索引,如果可以應該指定一個前綴長度。短索引不僅可以提高查詢速度還可以節省磁盤空間和I/O操作;
3.索引列排序
MySQL查詢只使用一個索引,因此如果where子句中已經使用了該索引,那麼order by中的列是不會使用索引的。因此數據庫默認排序可以符合要求的情況下不要使用排序操作;儘量不要包含多個列的排序,如果需要最好給這些列創建複合索引;
4.like語句操作
一般情況下不鼓勵使用like操作,如果非使用不可,如果使用也是一個問題。like“%aaa%”不會使用索引,而like“aaa%”可以使用索引;
5.不要在列上進行運算
例如:select * from users where YEAR(adddate)<2007,將在每個行上進行運算,這將導 致 索 引 失 效 而 進 行 全 表 掃 描 , 因 此 我 們 可 以 改 成 : select * from users where adddate<’2007-01-01′

索引總結:
MySQL只對以下操作符才使用索引: < ,<=,=,>=,between,in,以及某些時候的like。而理論上每張表裏面最多可創建16個索引,不過除非數據量真的很多,否則過多的使用索引也不是那麼好玩的。
建議:一個表的索引數最好不要超過 6 個,若太多則應考慮一些不常使用到的列上建的 索引是否有必要。

六.MySQL中SQL的常見優化策略
1.避免全表掃描
對查詢進行優化,避免全局掃描,首先應該考慮在where 和 order 設計的列上建立索引;
2.便面null值判斷
儘量避免在where字句中對字段進行null值判斷,否則將導致引擎放棄使用索引而進行全局掃描;如:
select id from t where num is null 可以在 num 上設置默認值 0,確保表中 num 列沒有 null 值,然後這樣查詢: select id from t where num=0
3.避免等值判斷
儘量避免在where子句中使用!= 或者<>,否則引擎將放棄使用索引而進行全掃描;
4.避免使用or邏輯
應該避免在where子句中使用or來連接條件,否則將導致引擎放棄使用索引而進行全局掃描:
select id from t where num=10 or num=20
可以這樣查詢: select id from t where num=10 union all select id from t where num=20

5.慎用in和not in邏輯
in 和 not in也要慎用,否則會導致全表掃描
select id from t1 where num in(select id from t2 where id > 10)
此時外層查詢會全表掃描,不使用索引。
可以修改爲:
select id from t1,(select id from t1 where id > 10)t2 where t1.id = t2.id
此時索引被使用,可以明顯提升查詢效率。

6.注意模糊查詢
下面的查詢也將導致全表掃描:
select id from t where name like ‘%abc%’ 模糊查詢如果是必要條件時;
可以使用 select id from t where name like 'abc%'來實現模
糊查詢,此時索引將被使用。如果頭匹配是必要邏輯,建議使用全文搜索引擎(Elastic search、 Lucene、Solr 等)。

7.避免查詢條件中字段計算
行全表掃描。
如:
select id from t where num/2=100
應改爲:
select id from t where num=100*2

8.避免查詢條件中對字段進行函數操作
應儘量避免在 where 子句中對字段進行函數操作,這將導致引擎放棄使用索引而進行 全表掃描。如:
select id from t where substring(name,1,3)=‘abc’–name
以 abc 開頭的 id 應改爲:
select id from t where name like ‘abc%’

9.where子句“=”左邊注意點
不要在where字句中的“=”左邊進行函數運算,算術運算,或其他表達式運算,否則系統可能無法正確使用索引。

10.組合索引的使用
在使用索引字段作爲條件時,該索引是符合索引,那麼必須使用到該索引中的第一個字段作爲條件才能保證系統使用該索引,否則該索引不會被使用。

11.不要定義無意義的查詢
不要寫一些沒有意義的查詢,如需要生成一個空表結構: select col1,col2 into #t from t where 1=0 這類代碼不會返回任何結果集,但是會消耗系統資源的,應改成這樣: create table #t(…)

12.exists
很多時候用exists代替in是一個好的選擇:
select num from a where num in(select num from b)
用下面的語句替換:
select num from a where exists(select 1 from b where num=a.num)

13.索引也有可能失效
並不是所有索引對查詢都有效,SQL 是根據表中數據來進行查詢優化的,當索引列有大 量數據重複時,SQL 查詢可能不會去利用索引,如一表中有字段 sex,male、female 幾乎各 一半,那麼即使在 sex 上建了索引也對查詢效率起不了作用。

14.表格字段類型選擇
儘量使用數字型字段,若只含數值信息的字段儘量不要設計爲字符型,這會降低查詢和 連接的性能,並會增加存儲開銷。這是因爲引擎在處理查詢和連接時會逐個比較字符串中每 一個字符,而對於數字型而言只需要比較一次就夠了。 儘可能的使用 varchar 代替 char ,因爲首先可變長度字段存儲空間小,可以節省存儲 空間,其次對於查詢來說,在一個相對較小的字段內搜索效率顯然要高些。

15.查詢語句中的字段
任何地方都不要使用select * from ,用具體的字段代替 * 不要返回用不到的字段

16索引無關優化
不使用*、儘量不使用 union,union all 等關鍵字、儘量不使用 or 關鍵字、儘量使用等 值判斷。
表連接建議不超過 5 個。如果超過 5 個,則考慮表格的設計。(互聯網應用中)
表連接方式使用外聯優於內聯。
外連接有基礎數據存在。如:A left join B,基礎數據是 A。
A inner join B,沒有基礎數據的,先使用笛卡爾積完成全連接,在根據連接條件得到內 連接結果集。
大數據量級的表格做分頁查詢時,如果頁碼數量過大,則使用子查詢配合完成分頁邏輯。
Select * from table limit 1000000, 10
Select * from table where id in (select pk from table limit 100000, 10

17.MySQL+MyCat分庫分表
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章