1. SQL入門
1.1. SQL語言功能
可以把 SQL 語言按照功能劃分成以下的 4 個部分:
- DDL,英文叫做 Data Definition Language,也就是數據定義語言,它用來定義我們的數據庫對象,包括數據庫、數據表和列。通過使用 DDL,我們可以創建,刪除和修改數據庫和表結構。
- DML,英文叫做 Data Manipulation Language,數據操作語言,我們用它操作和數據庫相關的記錄,比如增加、刪除、修改數據表中的記錄。
- DCL,英文叫做 Data Control Language,數據控制語言,我們用它來定義訪問權限和安全級別。
- DQL,英文叫做 Data Query Language,數據查詢語言,我們用它查詢想要的記錄,它是 SQL 語言的重中之重。在實際的業務中,我們絕大多數情況下都是在和查詢打交道,因此學會編寫正確且高效的查詢語句,是學習的重點。
SQL 大小寫的問題:
- 表名、表別名、字段名、字段別名等都小寫;
- SQL 保留字、函數名、綁定變量等都大寫。
1.2. DB、DBS 和 DBMS 的區別是什么
DBMS 的英文全稱是 DataBase Management System,數據庫管理系統,實際上它可以對多個數據庫進行管理,所以你可以理解為 DBMS = 多個數據庫(DB) + 管理程序。
DB 的英文是 DataBase,也就是數據庫。數據庫是存儲數據的集合,你可以把它理解為多個數據表。
DBS 的英文是 DataBase System,數據庫系統。它是更大的概念,包括了數據庫、數據庫管理系統以及數據庫管理人員 DBA。
這里需要注意的是,雖然我們有時候把 Oracle、MySQL 等稱之為數據庫,但確切講,它們應該是數據庫管理系統,即 DBMS。
1.3. 常用DBMS和類型
數據庫類型:
- 關系型數據庫:關系型數據庫(RDBMS)就是建立在關系模型基礎上的數據庫,SQL 就是關系型數據庫的查詢語言。
- 鍵值型數據庫:鍵值型數據庫通過 Key-Value 鍵值的方式來存儲數據,其中 Key 和 Value 可以是簡單的對象,也可以是復雜的對象。Key 作為唯一的標識符,優點是查找速度快,在這方面明顯優于關系型數據庫,同時缺點也很明顯,它無法像關系型數據庫一樣自由使用條件過濾(比如 WHERE),如果你不知道去哪里找數據,就要遍歷所有的鍵,這就會消耗大量的計算。鍵值型數據庫典型的使用場景是作為內容緩存。Redis 是最流行的鍵值型數據庫。
- 文檔型數據庫:文檔型數據庫用來管理文檔,在數據庫中文檔作為處理信息的基本單位,一個文檔就相當于一條記錄,MongoDB 是最流行的文檔型數據庫。
- 搜索引擎:搜索引擎也是數據庫檢索中的重要應用,常見的全文搜索引擎有 Elasticsearch、Splunk 和 Solr。雖然關系型數據庫采用了索引提升檢索效率,但是針對全文索引效率卻較低。搜索引擎的優勢在于采用了全文搜索的技術,核心原理是“倒排索引”。
- 列式數據庫:列式數據庫是相對于行式存儲的數據庫,Oracle、MySQL、SQL Server 等數據庫都是采用的行式存儲(Row-based),而列式數據庫是將數據按照列存儲到數據庫中,這樣做的好處是可以大量降低系統的 I/O,適合于分布式文件系統,不足在于功能相對有限。
- 圖形數據庫:圖形數據庫,利用了圖這種數據結構存儲了實體(對象)之間的關系。最典型的例子就是社交網絡中人與人的關系,數據模型主要是以節點和邊(關系)來實現,特點在于能高效地解決復雜的關系問題。
SQL:
關系型數據庫絕對是 DBMS 的主流,其中使用最多的 DBMS 分別是 Oracle、MySQL 和 SQL Server。
NoSQL:
NoSQL = No, SQL!
泛指非關系型數據庫,鍵值型、文檔型、搜索引擎、列式存儲和圖形數據庫等都屬于 NoSQL 陣營。
NoSQL 對 SQL 做出了很好的補充,它可以讓我們在云計算時代,更好地使用數據庫技術,比如快速讀寫,這樣可以用低廉的成本,更方便進行擴展。
DBMS使用場景:
比如 Oracle 作為市場占有率最高的商用數據庫軟件,適合大型的跨國企業,而針對輕量級的桌面數據庫,我們采用 Access 就可以了。對于免費開源的產品來說,可以選用 MySQL 或者 MariaDB。同時在 NoSQL 陣營中,我們也需要了解鍵值型、文檔型、搜索引擎、列式數據庫和圖形數據庫的區別。
2. SQL的執行方式
2.1. Oracle 中的 SQL 執行過程
SQL 在 Oracle 中的執行過程:
- 語法檢查:檢查 SQL 拼寫是否正確,如果不正確,Oracle 會報語法錯誤。
- 語義檢查:檢查 SQL 中的訪問對象是否存在。比如我們在寫 SELECT 語句的時候,列名寫錯了,系統就會提示錯誤。語法檢查和語義檢查的作用是保證 SQL 語句沒有錯誤。
- 權限檢查:看用戶是否具備訪問該數據的權限。
- 共享池檢查:共享池(Shared Pool)是一塊內存池,最主要的作用是緩存 SQL 語句和該語句的執行計劃。Oracle 通過檢查共享池是否存在 SQL 語句的執行計劃,來判斷進行軟解析,還是硬解析。那軟解析和硬解析又該怎么理解呢?
- 在共享池中,Oracle 首先對 SQL 語句進行 Hash 運算,然后根據 Hash 值在庫緩存(Library Cache)中查找,如果存在 SQL 語句的執行計劃,就直接拿來執行,直接進入“執行器”的環節,這就是軟解析。
- 如果沒有找到 SQL 語句和執行計劃,Oracle 就需要創建解析樹進行解析,生成執行計劃,進入“優化器”這個步驟,這就是硬解析。
- 優化器:優化器中就是要進行硬解析,也就是決定怎么做,比如創建解析樹,生成執行計劃。
- 執行器:當有了解析樹和執行計劃之后,就知道了 SQL 該怎么被執行,這樣就可以在執行器中執行語句了。
共享池是 Oracle 中的術語,包括了庫緩存,數據字典緩沖區等。庫緩存這一個步驟,決定了 SQL 語句是否需要進行硬解析。為了提升 SQL 的執行效率,我們應該盡量避免硬解析,因為在 SQL 的執行過程中,創建解析樹,生成執行計劃是很消耗資源的。
在 Oracle 中,綁定變量是它的一大特色。綁定變量就是在 SQL 語句中使用變量,通過不同的變量取值來改變 SQL 的執行結果。這樣做的好處是能提升軟解析的可能性,不足之處在于可能會導致生成的執行計劃不夠優化,因此是否需要綁定變量還需要視情況而定。
2.2. MySQL 中的 SQL 執行過程
MySQL 是典型的 C/S 架構,即 Client/Server 架構,服務器端程序使用的mysqld 。整體的 MySQL 流程如下圖所示:
MySQL 由三層組成:
- 連接層:客戶端和服務器端建立連接,客戶端發送 SQL 至服務器端;
- SQL 層:對 SQL 語句進行查詢處理;
- 存儲引擎層:與數據庫文件打交道,負責數據的存儲和讀取。
其中 SQL 層與數據庫文件的存儲方式無關,SQL 層的結構:
- 查詢緩存:Server 如果在查詢緩存中發現了這條 SQL 語句,就會直接將結果返回給客戶端;如果沒有,就進入到解析器階段。需要說明的是,因為查詢緩存往往效率不高,所以在 MySQL8.0 之后就拋棄了這個功能。
- 解析器:在解析器中對 SQL 語句進行語法分析、語義分析。
- 優化器:在優化器中會確定 SQL 語句的執行路徑,比如是根據全表檢索,還是根據索引來檢索等。
- 執行器:在執行之前需要判斷該用戶是否具備權限,如果具備權限就執行 SQL 查詢并返回結果。在 MySQL8.0 以下的版本,如果設置了查詢緩存,這時會將查詢結果進行緩存。
SQL 語句在 MySQL 中的流程是:SQL 語句→緩存查詢→解析器→優化器→執行器。在一部分中,MySQL 和 Oracle 執行 SQL 的原理是一樣的。
與 Oracle 不同的是,MySQL 的存儲引擎采用了插件的形式,每個存儲引擎都面向一種特定的數據庫應用環境。同時開源的 MySQL 還允許開發人員設置自己的存儲引擎。
下面是一些常見的存儲引擎:
- InnoDB 存儲引擎:它是 MySQL 5.5 版本之后默認的存儲引擎,最大的特點是支持事務、行級鎖定、外鍵約束等。
- MyISAM 存儲引擎:在 MySQL 5.5 版本之前是默認的存儲引擎,不支持事務,也不支持外鍵,最大的特點是速度快,占用資源少。
- Memory 存儲引擎:使用系統內存作為存儲介質,以便得到更快的響應速度。不過如果 mysqld 進程崩潰,則會導致所有的數據丟失,因此我們只有當數據是臨時的情況下才使用 Memory 存儲引擎。
- NDB 存儲引擎:也叫做 NDB Cluster 存儲引擎,主要用于 MySQL Cluster 分布式集群環境,類似于 Oracle 的 RAC 集群。
- Archive 存儲引擎:它有很好的壓縮機制,用于文件歸檔,在請求寫入時會進行壓縮,所以也經常用來做倉庫。
數據庫的設計在于表的設計, MySQL 的一大特色就是提供了各種存儲引擎以供選擇,不同的存儲引擎有各自的使用場景,我們可以針對每張表選擇適合的存儲引擎。