自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

MySQL系列之執(zhí)行SQL 語句時發(fā)生了什么?

數(shù)據(jù)庫 MySQL
MySQL是一個客戶端、服務端的架構(gòu)。我們平時使用的大部分程序app其實是由兩部分組成的,一部分是客戶端程序,一部分是服務器程序。

[[408201]]

前言

當我們用 navicat、mysql workbench 等mysql 的客戶端執(zhí)行一條sql語句后,我們就能得到相應的結(jié)果。例如:

那么這個過程發(fā)生了什么呢?

執(zhí)行一條sql 就是一次Rpc的調(diào)用

mysql 是一個客戶端、服務端的架構(gòu)。我們平時使用的大部分程序app其實是由兩部分組成的,一部分是客戶端程序,一部分是服務器程序。

以我們常用的微信、qq 為例。我們手機里面裝的客戶端,機房的服務器中運行著server端。我們平時發(fā)信息都是其實都是用客戶端和服務端打交道。比如你和你女朋友發(fā)信息的過程:

  1. 消息被客戶端包裝了一下,添加了發(fā)送者和接收者信息,然后從你的微信客戶端傳送給微信服務器;
  2. 微信服務器從消息里獲取到它的發(fā)送者和接收者,根據(jù)消息的接收者信息把這條消息送達到你女朋友的微信客戶端,你女朋友的微信客戶端里就顯示出你給他發(fā)了一條消息。

mysql的使用過程跟這個是一樣的,它的服務器程序直接和我們存儲的數(shù)據(jù)打交道,然后可以有好多客戶端程序連接到這個服務器程序,發(fā)送增刪改查的請求,然后服務器就響應這些請求,從而操作它維護的數(shù)據(jù)。

主要流程如下:

所以,一條sql的執(zhí)行,就是一次rpc的調(diào)用。后面有時間也會分享RPC 相關(guān)的東西,一起交流學習!

服務器怎么處理客戶端請求

不管我們用了哪種客戶端和服務器進程是采用哪種方式進行通信,最后實現(xiàn)的效果都是:客戶端進程向服務器進程發(fā)送一段文本(MySQL語句),服務器進程處理后再向客戶端進程發(fā)送一段文本(處理結(jié)果)。主要過程如下:

從圖中我們可以看出,服務器程序處理來自客戶端的查詢請求大致需要經(jīng)過三個部分,分別是 連接管理、解析優(yōu)化與執(zhí)行、存儲引擎三個部分。其中連接管理、解析優(yōu)化與執(zhí)行常常被分為mysql的 server 層。

連接管理

客戶端進程可以采用TCP/IP、命名管道或共享內(nèi)存、Unix域套接字這幾種方式之一來與服務器進程建立連接。

對連接的管理也使用了池化技術(shù):每當有一個客戶端進程連接到服務器進程時,服務器進程都會創(chuàng)建一個線程來專門處理與這個客戶端的交互,當該客戶端退出時會與服務器斷開連接,服務器并不會立即把與該客戶端交互的線程銷毀掉,而是把它緩存起來,在另一個新的客戶端再進行連接時,把這個緩存的線程分配給該新客戶端。這樣就起到了不頻繁創(chuàng)建和銷毀線程的效果,從而節(jié)省開銷。

查詢緩存

由于表經(jīng)常更新,查詢緩存的失效頻繁,查詢緩存往往利大于弊。,MySQL 8.0 版本開始直接將查詢緩存的整塊功能刪掉了。

語法解析

如果查詢緩存沒有命中,接下來就需要進入正式的查詢階段了。因為客戶端程序發(fā)送過來的請求只是一段文本而已,所以MySQL服務器程序首先要對這段文本做分析,判斷請求的語法是否正確,然后從文本中將要查詢的表、各種查詢條件都提取出來放到MySQL服務器內(nèi)部使用的一些數(shù)據(jù)結(jié)構(gòu)上來。

查詢優(yōu)化

經(jīng)過了語法解析,MySQL 就知道你要做什么了。在開始執(zhí)行之前,還要先經(jīng)過查詢優(yōu)化的處理。優(yōu)化處理是指在表里面有多個索引的時候,決定使用哪個索引;或者在一個語句有多表關(guān)聯(lián)(join)的時候,決定各個表的連接順序。我們可以使用EXPLAIN語句來查看某個語句的執(zhí)行計劃 。

大部分優(yōu)化的邏輯是基于成本的優(yōu)化。在MySQL中一條查詢語句的執(zhí)行成本是由兩個方面組成的 :

  • I/O成本 :從磁盤到內(nèi)存這個加載的過程損耗的時間稱之為I/O成本。
  • CPU成本 :讀取以及檢測記錄是否滿足對應的搜索條件、對結(jié)果集進行排序等這些操作損耗的時間稱之為CPU成本。

對于InnoDB存儲引擎來說 ,mysql規(guī)定讀取一個頁面花費的成本默認是1.0,讀取以及檢測一條記錄是否符合搜索條件的成本默認是0.2 。

拿單表查詢來舉例,成本計算步驟如下:

  • 根據(jù)搜索條件,找出所有可能使用的索引
  • 計算全表掃描的代價
  • 計算使用不同索引執(zhí)行查詢的代價
  • 對比各種執(zhí)行方案的代價,找出成本最低的那一個。

存儲引擎

  • 截止到服務器程序完成了查詢優(yōu)化為止,還沒有真正的去訪問真實的數(shù)據(jù)表,MySQL服務器把數(shù)據(jù)的存儲和提取操作都封裝到了一個叫存儲引擎的模塊里。我們知道表是由一行一行的記錄組成的,但這只是一個邏輯上的概念,物理上如何表示記錄,怎么從表中讀取數(shù)據(jù),怎么把數(shù)據(jù)寫入具體的物理存儲器上,這都是存儲引擎負責的事情。為了實現(xiàn)不同的功能,MySQL提供了各式各樣的存儲引擎,不同存儲引擎管理的表具體的存儲結(jié)構(gòu)可能不同,采用的存取算法也可能不同。
  • 為了管理方便,所以大部分人把連接管理、查詢緩存、語法解析、查詢優(yōu)化這些并不涉及真實數(shù)據(jù)存儲的功能劃分為MySQL server的功能,
  • 把真實存取數(shù)據(jù)的功能劃分為存儲引擎的功能。

執(zhí)行器

執(zhí)行器就是各種不同的存儲引擎向上邊的MySQL server層提供統(tǒng)一的調(diào)用接口(也就是存儲引擎API),包含了幾十個底層函數(shù),像"讀取索引第一條內(nèi)容"、"讀取索引下一條內(nèi)容"、"插入記錄"等等。

比如執(zhí)行一條查詢sql 時,開始執(zhí)行的時候,要先判斷一下你對這個表 有沒有執(zhí)行查詢的權(quán)限,如果沒有,就會返回沒有權(quán)限的錯誤;

拿我們開頭的例子中,id字段沒有索引,那么執(zhí)行器的執(zhí)行流程是這樣的:

  • 調(diào)用 InnoDB 引擎接口取這個表的第一行,判斷 ID 值是不是 10,如果不是則跳過,如果是則將這行存在結(jié)果集中;
  • 調(diào)用引擎接口取“下一行”,重復相同的判斷邏輯,直到取到這個表的最后一行。
  • 執(zhí)行器將上述遍歷過程中所有滿足條件的行組成的記錄集作為結(jié)果集返回給客戶端。

對于有索引的表,執(zhí)行的邏輯也差不多。第一次調(diào)用的是“取滿足條件的第一行”這個接口,之后循環(huán)取“滿足條件的下一行”這個接口,這些接口都是引擎中已經(jīng)定義好的。但是對于 插入、刪除和修改的sql語句,還要涉及到redolog、undolog 和binlog 的操作。這個我們有空再聊。

所以只需按照生成的執(zhí)行計劃調(diào)用底層存儲引擎提供的API(執(zhí)行器),獲取到數(shù)據(jù)后返回給客戶端就好了。一條sql 語句就執(zhí)行完成了。

 

責任編輯:姜華 來源: 今日頭條
相關(guān)推薦

2022-05-31 13:58:09

MySQL查詢語句

2019-11-12 14:41:41

Redis程序員Linux

2021-01-18 08:23:23

內(nèi)存時底層CPU

2020-08-20 11:50:31

語言類型轉(zhuǎn)換代碼

2021-11-23 23:31:43

C語言數(shù)據(jù)類型系統(tǒng)

2023-03-31 08:12:30

操作系統(tǒng)nanosleep信號

2022-05-26 23:36:36

SQLMySQL數(shù)據(jù)

2020-08-17 12:47:07

Mozilla裁員瀏覽器

2010-02-07 09:00:29

AndroidLinux Kerne

2019-08-26 09:35:25

命令ping抓包

2021-04-11 10:40:16

Git軟件開發(fā)

2018-11-05 14:54:18

MySQLSQL語句數(shù)據(jù)庫

2015-07-03 09:27:43

網(wǎng)絡(luò)閏秒

2020-09-01 11:40:01

HTTPJavaTCP

2023-08-29 16:26:20

Linux命令行

2019-09-16 17:16:29

Hadoop數(shù)據(jù)湖數(shù)據(jù)結(jié)構(gòu)

2021-12-16 15:58:48

Linux內(nèi)存微軟

2022-06-03 08:12:52

InnoDB插入MySQL

2017-09-06 16:20:51

2023-11-02 08:00:00

ClickHouse數(shù)據(jù)庫
點贊
收藏

51CTO技術(shù)棧公眾號