作者:yandeng,騰訊 PCG 應用開發工程師 1.數據庫基礎1.1 MySQL 架構和其它數據庫相比,MySQL 有點與眾不同,它的架構可以在多種不同場景中應用并發揮良好作用。主要體現在存儲引擎的架構上,插件式的存儲引擎架構將查詢處理和其它的系統任務以及數據的存儲提取相分離。這種架構可以根據業務的需求和實際需要選擇合適的存儲引擎,各層介紹: 1.1.1 連接層最上層是一些客戶端和連接服務,包含本地 sock 通信和大多數基于客戶端/服務端工具實現的類似于 tcp/ip 的通信。主要完成一些類似于連接處理、授權認證、及相關的安全方案。在該層上引入了線程池的概念,為通過認證安全接入的客戶端提供線程。同樣在該層上可以實現基于 SSL 的安全鏈接。服務器也會為安全接入的每個客戶端驗證它所具有的操作權限。 1.1.2 服務層1.1.3 引擎層存儲引擎層,存儲引擎真正的負責了 MySQL 中數據的存儲和提取,服務器通過 API 與存儲引擎進行通信。不同的存儲引擎具有的功能不同,這樣我們可以根據自己的實際需要進行選取。 1.1.4 存儲層數據存儲層,主要是將數據存儲在運行于裸設備的文件系統之上,并完成與存儲引擎的交互。 1.2 數據引擎不同的存儲引擎都有各自的特點,以適應不同的需求,如表所示。為了做出選擇,首先要考慮每一個存儲引擎提供了哪些不同的功能。 1.2.1 MyISAM使用這個存儲引擎,每個 MyISAM 在磁盤上存儲成三個文件。
1.2.2 InnoDBInnoDB 是默認的數據庫存儲引擎,他的主要特點有:
1.2.3 Memory將數據存在內存,為了提高數據的訪問速度,每一個表實際上和一個磁盤文件關聯。文件是 frm。
1.3 表與字段設計1.3.1 數據庫基本設計規范
1.3.2 數據庫字段設計規范
1.3.3 索引設計規范
1.3.4 數據庫 SQL 開發規范
1.4 范式與反范式1.4.1 第一范式該范式是為了排除 重復組 的出現,因此要求數據庫的每個列的值域都由原子值組成;每個字段的值都只能是單一值。1971 年埃德加·科德提出了第一范式。即表中所有字段都是不可再分的。解決方案:想要消除重復組的話,只要把每筆記錄都轉化為單一記錄即可。 1.4.2 第二范式表中必須存在業務主鍵,并且非主鍵依賴于全部業務主鍵。解決方案:拆分將依賴的字段單獨成表。 1.4.3 第三范式表中的非主鍵列之間不能相互依賴,將不與 PK 形成依賴關系的字段直接提出單獨成表即可。 1.5 sql 索引
1.6 join 連表1.6.1 JOIN 按照功能大致分為如下三類:
1.6.2 join 的原理MySQL 使用了嵌套循環(Nested-Loop Join)的實現方式。Nested-Loop Join 需要區分驅動表和被驅動表,先訪問驅動表,篩選出結果集,然后將這個結果集作為循環的基礎,訪問被驅動表過濾出需要的數據。Nested-Loop Join 分下面幾種類型:
相關圖片來源于網絡
這個 buffer 被稱為 join buffer,顧名思義,就是用來緩存 join 需要的字段。MySQL 默認 buffer 大小 256K,如果有 n 個 join 操作,會生成 n-1 個 join buffer。 1.6.3 join 的優化
![]()
2.數據進階2.1 sql 執行過程![]() 如上圖所示,當向 MySQL 發送一個請求的時候,MySQL 到底做了什么:
MySQL 的查詢優化器使用很多策略來生成一個最優的執行計劃。優化策略可以簡單的分為兩種:
使用 show status like 'Last_query_cost’ 可以查詢上次執行的語句的成本,單位為數據頁。 ![]() ![]() 2.2 sql 查詢計劃使用 explain 進行執行計劃分析: ![]() ![]() ![]() 2.3 sql 索引優化遵循索引原則適合大部分的常規數據庫查詢場景,但不是所有的索引都能符合預期,從索引原理本身來分析對索引的創建會更有幫助。
2.3.1 前綴索引當要索引的列字符很多時 索引則會很大且變慢( 可以只索引列開始的部分字符串 節約索引空間 從而提高索引效率 ) 例如:一個數據表的 x_name 值都是類似 23213223.434323.4543.4543.34324 這種值,如果以整個字段值做索引,會使索引文件過大,但是如果設置前 7 位來做索引則不會出現重復索引值的情況了。 ![]() 查詢效率會大大提升: ![]() 2.3.2 聯合索引順序
使用選擇基數更高(不重復的數據)的字段作為最左索引: ![]() 2.3.3 聯合索引左前綴匹配![]()
2.4 慢查詢分析2.4.1 先對 sql 語句進行 explain,查看語句存在的問題2.4.2 使用 show profile 查看執行耗時,分析具體耗時原因show profile 的使用指引: ![]() 2.5 改表與 sql 日志2.5.1 改表改表會直接觸發表鎖,改表過程非常耗時,對于大表修改,無論是字段類型調整還是字段增刪,都需要謹慎操作,防止業務表操作被阻塞,大表修改往往有以下幾種方式。
常用方法: ![]() 2.5.2 sql 日志![]() ![]() 2.6 分庫與分表2.6.1 數據庫瓶頸不管是 IO 瓶頸,還是 CPU 瓶頸,最終都會導致數據庫的活躍連接數增加,進而逼近甚至達到數據庫可承載活躍連接數的閾值。在業務 Service 來看就是,可用數據庫連接少甚至無連接可用。接下來就可以想象了吧(并發量、吞吐量、崩潰)。
第二種:網絡 IO 瓶頸,請求的數據太多,網絡帶寬不夠 -> 分庫。
第二種:單表數據量太大,查詢時掃描的行太多,SQL 效率低,CPU 率先出現瓶頸 -> 水平分表。 2.6.2 分庫分表
概念:以字段為依據,按照一定策略(hash、range 等),將一個庫中的數據拆分到多個庫中。結果:每個庫的結構都一樣;每個庫的數據都不一樣,沒有交集;所有庫的并集是全量數據;場景:系統絕對并發量上來了,分表難以根本上解決問題,并且還沒有明顯的業務歸屬來垂直分庫。分析:庫多了,io 和 cpu 的壓力自然可以成倍緩解。
概念:以字段為依據,按照一定策略(hash、range 等),將一個表中的數據拆分到多個表中。結果:每個表的結構都一樣;每個表的數據都不一樣,沒有交集;所有表的并集是全量數據。 場景:系統絕對并發量并沒有上來,只是單表的數據量太多,影響了 SQL 效率,加重了 CPU 負擔,以至于成為瓶頸。 分析:表的數據量少了,單次 SQL 執行效率高,自然減輕了 CPU 的負擔。
概念:以表為依據,按照業務歸屬不同,將不同的表拆分到不同的庫中。 結果:每個庫的結構都不一樣;每個庫的數據也不一樣,沒有交集;所有庫的并集是全量數據。 場景:系統絕對并發量上來了,并且可以抽象出單獨的業務模塊。 分析:到這一步,基本上就可以服務化了。例如,隨著業務的發展一些公用的配置表、字典表等越來越多,這時可以將這些表拆到單獨的庫中,甚至可以服務化。再有,隨著業務的發展孵化出了一套業務模式,這時可以將相關的表拆到單獨的庫中,甚至可以服務化。
概念:以字段為依據,按照字段的活躍性,將表中字段拆到不同的表(主表和擴展表)中。 結果:每個表的結構都不一樣;每個表的數據也不一樣,一般來說,每個表的字段至少有一列交集,一般是主鍵,用于關聯數據;所有表的并集是全量數據。 2.6.3 分庫分表工具目前市面上的分庫分表中間件相對較多,其中基于代理方式的有 MySQL Proxy 和 Amoeba, 基于 Hibernate 框架的是 Hibernate Shards,基于 jdbc 的有當當 sharding-jdbc, 基于 mybatis 的類似 maven 插件式的有蘑菇街的蘑菇街 TSharding, 通過重寫 spring 的 ibatis template 類的 Cobar Client。 還有一些大公司的開源產品: ![]() 3.分布式數據庫3.1 什么是分布式數據庫分布式系統數據庫系統原理(第三版)中的描述:“我們把分布式數據庫定義為一群分布在計算機網絡上、邏輯上相互關聯的數據庫。分布式數據庫管理系統(分布式 DBMS)則是支持管理分布式數據庫的軟件系統,它使得分布對于用戶變得透明。有時,分布式數據庫系統(Distributed Database System,DDBS)用于表示分布式數據庫和分布式 DBMS 這兩者。 在以上表述中,“一群分布在網絡上、邏輯上相互關聯”是其要義。在物理上一群邏輯上相互關聯的數據庫可以分布式在一個或多個物理節點上。當然,主要還是應用在多個物理節點。這一方面是 X86 服務器性價比的提升有關,另一方面是因為互聯網的發展帶來了高并發和海量數據處理的需求,原來的單物理服務器節點不足以滿足這個需求。 3.2 分布式數據庫的理論基礎1. CAP 理論首先,分布式數據庫的技術理論是基于單節點關系數據庫的基本特性的繼承,主要涉及事務的 ACID 特性、事務日志的容災恢復性、數據冗余的高可用性幾個要點。 其次,分布式數據的設計要遵循 CAP 定理,即:一個分布式系統不可能同時滿足 一致性( Consistency ) 、可用性 ( Availability ) 、分區容 忍 性 ( Partition tolerance ) 這三個基本需求,最 多只能同時滿足其中的兩項, 分區容錯性 是不能放棄的,因此架構師通常是在可用性和一致性之間權衡。這里的權衡不是簡單的完全拋棄,而是考慮業務情況作出的犧牲,或者用互聯網的一個術語“降級”來描述。 CAP 三個特性描述如下 :一致性:確保分布式群集中的每個節點都返回相同的 、 最近 更新的數據 。一致性是指每個客戶端具有相同的數據視圖。有多種類型的一致性模型 , CAP 中的一致性是指線性化或順序一致性,是強一致性。 可用性:每個非失敗節點在合理的時間內返回所有讀取和寫入請求的響應。為了可用,網絡分區兩側的每個節點必須能夠在合理的時間內做出響應。 分區容忍性:盡管存在網絡分區,系統仍可繼續運行并 保證 一致性。網絡分區已成事實。保證分區容忍度的分布式系統可以在分區修復后從分區進行適當的恢復。 2. BASE 理論 基于 CAP 定理的權衡,演進出了 BASE 理論 ,BASE 是 Basically Available(基本可用)、Soft state(軟狀態)和 Eventually consistent(最終一致性)三個短語的縮寫。BASE 理論的核心思想是:即使無法做到強一致性,但每個應用都可以根據自身業務特點,采用適當的方式來使系統達到最終一致性。 BA:Basically Available 基本可用,分布式系統在出現故障的時候,允許損失部分可用性,即保證核心可用;S:Soft state 軟狀態,允許系統存在中間狀態,而該中間狀態不會影響系統整體可用性;E:Consistency 最終一致性,系統中的所有數據副本經過一定時間后,最終能夠達到一致的狀態。 BASE 理論本質上是對 CAP 理論的延伸,是對 CAP 中 AP 方案的一個補充。 3.3 分布式數據庫的架構演變
|
|
來自: 520jefferson > 《sql》