精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

一條SQL查詢語句是怎么去執行的?(中)

jf_78858299 ? 來源:蟬沐風的碼場 ? 作者:蟬沐風 ? 2023-03-03 09:58 ? 次閱讀

2. 解析與優化

服務器收到客戶端傳來的請求之后,還需要經過查詢緩存、詞法語法解析和預處理、查詢優化的處理。

2.1 查詢緩存

如果我們兩次都執行同一條查詢指令,第二次的響應時間會不會比第一次的響應時間短一些?

之前使用過Redis緩存工具的讀者應該會有這個很自然的想法,MySQL收到查詢請求之后應該先到緩存中查看一下,看一下之前是不是執行過這條指令。如果緩存命中,則直接返回結果;否則重新進行查詢,然后加入緩存。

MySQL確實內部自帶了一個緩存模塊。

現在有一張500W行且沒有添加索引的數據表,我執行以下命令兩次,第二次會不會變得很快?

SELECT * FROM t_user WHERE user_name = '蟬沐風'

并不會!說明緩存沒有生效,為什么?MySQL默認是關閉自身的緩存功能的,查看一下query_cache_type變量設置。

mysql> show variables like 'query_cache_type';
+------------------------------+---------+
| Variable_name                | Value   |
+------------------------------+---------+
| query_cache_type             | OFF     |
+------------------------------+---------+

默認關閉就意味著不推薦,MySQL為什么不推薦用戶使用自己的緩存功能呢?

  1. MySQL自帶的緩存系統應用場景非常有限,它要求SQL語句必須一模一樣,多一個空格,變一個大小寫都被認為是兩條不同的SQL語句
  2. 緩存失效非常頻繁。只要一個表的數據有任何修改,針對該表的所有緩存都會失效。對于更新頻繁的數據表而言,緩存命中率非常低!

所以緩存的功能還是交給專業的ORM框架(比如MyBatis默認開啟一級緩存)或者獨立的緩存服務Redis更加適合。

MySQL8.0已經徹底移除了緩存功能

2.2 解析器 & 預處理器(Parser & Preprocessor)

現在跳過緩存這一步了,接下來需要做什么了?

如果我隨便在客戶端終端里輸入一個字符串chanmufeng,服務器返回了一個1064的錯誤

mysql> chanmufeng;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'chanmufeng' at line 1

服務器是怎么判斷出我的輸入是錯誤的呢?這就是MySQL的Parser解析器的作用了,它主要包含兩步,分別是詞法解析和語法分析。

2.2.1 詞法解析

以下面的SQL語句為例

SELECT * FROM t_user WHERE user_name = '蟬沐風' AND age > 3;

分析器先會做“詞法分析”,就是把一條完整的SQL語句打碎成一個個單詞,比如一條簡單的SQL語句,會打碎成8個符號,每個符號是什么類型,從哪里開始到哪里結束。

MySQL 從你輸入的SELECT這個關鍵字識別出來,這是一個查詢語句。它也要把字符串t_user識 別成“表名 t_user”,把字符串user_name識別成“列 user_name"。

2.2.2 語法分析

做完詞法解析,接下來需要做語法分析了。

根據詞法分析的結果,語法分析器會根據語法規則,判斷你輸入的這個 SQL 語句是否滿足 MySQL 語法,比如單引號是否閉合,關鍵詞拼寫是否正確等。

解析器會根據SQL語句生成一個數據結構,這個數據結構我們成為解析樹。

圖片我故意拼錯了SELECT關鍵字,MySQL報了語法錯誤,就是在語法分析這一步。

mysql> ELECT * FROM t_user WHERE user_name = '蟬沐風' AND age > 3;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'ELECT * FROM t_user WHERE user_name = '蟬沐風'' at line 1

詞法語法分析是一個非常基礎的功能,Java 的編譯器、百度搜索引擎如果要識別語句,必須也要有詞法語法分析功能。

任何數據庫的中間件,要解析 SQL完成路由功能,也必須要有詞法和語法分析功能,比如 Mycat,Sharding-JDBC(用到了Druid Parser)等都是如此。在市面上也有很多的開源的詞法解析的工具,比如 LEX,Yacc等。

2.2.3 預處理器

如果我們寫了一條語法和詞法都沒有問題的SQL,但是字段名和表名卻不存在,這個錯誤是在哪一個階段爆出的呢?

詞法解析和語法分析是無法知道數據庫里有什么表,有哪些字段的。要知道這些信息還需要解析階段的另一個工具——預處理器。

它會檢查生成的解析樹,解決解析器無法解析的語義。比如,它會檢查表和列名是否存在,檢查名字和別名,保證沒有歧義。預處理之后得到一個新的解析樹。

本質上,解析和預處理是一個編譯過程,涉及到詞法解析、語法和語義分析,更多細節我們不會探究,感興趣的讀者可以看一下編譯原理方面的書籍。

2.3 查詢優化器(Optimizer)與查詢執行計劃

到了這一步,MySQL終于知道我們想查詢的表和列以及相應的搜索條件了,是不是可以直接進行查詢了?

還不行。MySQL作者擔心我們寫的SQL太垃圾,所以有設計出一個叫做查詢優化器的東東,輔助我們提高查詢效率。

2.3.1 什么是查詢優化器?

一條 SQL語句是不是只有一種執行方式?或者說數據庫最終執行的 SQL是不是就是我們發送的 SQL?

不是。一條 SQL 語句是可以有很多種執行方式的,最終返回相同的結果,他們是等價的。

舉一個非常簡單的例子,比如你執行下面這樣的語句:

SELECT * FROM t1, t2 WHERE t1.id = 10 AND t2.id = 20
  • 既可以先從表 t1 里面取出 id=10 的記錄,再根據 id 值關聯到表 t2,再判斷 t2 里面 id 的值是否等于 20。
  • 也可以先從表 t2 里面取出 id=20 的記錄,再根據 id 值關聯到表 t1,再判斷 t1 里面 id 的值是否等于 10。

這兩種執行方法的邏輯結果是一樣的,但是執行的效率會有不同,如果有這么多種執行方式,這些執行方式怎么得到的?最終選擇哪一種去執行?根據什么判斷標準去選擇?

這個就是 MySQL的查詢優化器的模塊(Optimizer)的工作。

查詢優化器的目的就是根據解析樹生成不同的執行計劃(Execution Plan),然后選擇一種最優的執行計劃,MySQL 里面使用的是基于開銷(cost)的優化器,哪種執行計劃開銷最小,就用哪種。

2.3.2 優化器究竟做了什么?

舉兩個簡單的例子∶

  1. 當我們對多張表進行關聯查詢的時候,以哪個表的數據作為基準表。
  2. 有多個索引可以使用的時候,選擇哪個索引。

實際上,對于每一種數據庫來說,優化器的模塊都是必不可少的,他們通過復雜的算法實現盡可能優化查詢效率。

往細節上說,查詢優化器主要做了下面幾方面的優化:

  • 子查詢優化
  • 等價謂詞重寫
  • 條件化簡
  • 外連接消除
  • 嵌套連接消除
  • 連接消除
  • 語義優化

本文不會對優化的細節展開講解,大家先對MySQL的整體架構有所了解就可以了,具體細節之后單獨開篇介紹

但是優化器也不是萬能的,如果SQL語句寫得實在太垃圾,再牛的優化器也救不了你了。因此大家在編寫SQL語句的時候還是要有意識地進行優化。

2.3.3 執行計劃

優化完之后,得到一個什么東西呢?優化器最終會把解析樹變成一個查詢執行計劃。

查詢執行計劃展示了接下來執行查詢的具體方式,比如多張表關聯查詢,先查詢哪張表,在執行查詢的時候有多個索引可以使用,實際上該使用哪些索引。

MySQL提供了一個查看執行計劃的工具。我們在 SQL語句前面加上 EXPLAIN就可以看到執行計劃的信息。

mysql> EXPLAIN SELECT * FROM t_user WHERE user_name = '';
+----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table  | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra       |
+----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | t_user | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    1 |   100.00 | Using where |
+----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+-------------+

如果要得到更加詳細的信息,還可以用FORMAT=JSON,或者開啟optimizer trace

mysql> EXPLAIN FORMAT=JSON SELECT * FROM t_user WHERE user_name = '';

文本不會帶大家詳細了解執行計劃的每一個參數,內容很龐雜,大家先對MySQL的整體架構有所了解就可以了,具體細節之后單獨開篇介紹

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 服務器
    +關注

    關注

    12

    文章

    9024

    瀏覽量

    85186
  • TCP
    TCP
    +關注

    關注

    8

    文章

    1351

    瀏覽量

    78989
  • MySQL
    +關注

    關注

    1

    文章

    802

    瀏覽量

    26445
收藏 人收藏

    評論

    相關推薦

    在Delphi動態地使用SQL查詢語句

    在Delphi動態地使用SQL查詢語句般的數據庫管理系統,通常都需要應用
    發表于 05-10 11:10

    Database數據庫SQL語句

    如何用一條SQL語句清空數據庫多張表的記錄?請大神幫忙,謝謝
    發表于 03-01 00:57

    DSP執行一條語句的時間

    CPU配置成150M。高頻時鐘75M。 那么執行一條語句的時間是多少呢
    發表于 10-15 11:28

    select語句和update語句分別是怎么執行

    樣,但是具體的實現還是有區別的。 當然深入了解select和update的具體區別并不是只為了面試,當希望Mysql能夠高效的執行的時候,最好的辦法就是清楚的了解Mysql是如何執行查詢
    的頭像 發表于 11-03 09:41 ?3527次閱讀
    select<b class='flag-5'>語句</b>和update<b class='flag-5'>語句</b>分別是怎么<b class='flag-5'>執行</b>的

    一條SQL語句是怎么被執行

    直是想知道一條SQL語句是怎么被執行的,它執行的順序是怎樣的,然后查看總結各方資料,就有了下面
    的頭像 發表于 09-12 09:44 ?1493次閱讀
    <b class='flag-5'>一條</b><b class='flag-5'>SQL</b><b class='flag-5'>語句</b>是怎么被<b class='flag-5'>執行</b>的

    簡述SQL更新語句執行流程1

    之前我們講過了一條SQL查詢語句是如何執行的,那么插入(INSERT)、更新(UPDATE)和刪除(DELETE)操作的流程又是什么樣子呢?
    的頭像 發表于 02-14 15:40 ?590次閱讀
    簡述<b class='flag-5'>SQL</b>更新<b class='flag-5'>語句</b>的<b class='flag-5'>執行</b>流程1

    簡述SQL更新語句執行流程2

    之前我們講過了一條SQL查詢語句是如何執行的,那么插入(INSERT)、更新(UPDATE)和刪除(DELETE)操作的流程又是什么樣子呢?
    的頭像 發表于 02-14 15:40 ?506次閱讀
    簡述<b class='flag-5'>SQL</b>更新<b class='flag-5'>語句</b>的<b class='flag-5'>執行</b>流程2

    一條SQL查詢語句是怎么執行的?(上)

    MySQL是典型的`C/S架構`(客戶端/服務器架構),客戶端進程向服務端進程發送段文本(MySQL指令),服務器進程進行語句處理然后返回執行結果。
    的頭像 發表于 03-03 09:58 ?361次閱讀
    <b class='flag-5'>一條</b><b class='flag-5'>SQL</b><b class='flag-5'>查詢</b><b class='flag-5'>語句</b>是怎么<b class='flag-5'>去</b><b class='flag-5'>執行</b>的?(上)

    一條SQL查詢語句是怎么執行的?(下)

    MySQL是典型的`C/S架構`(客戶端/服務器架構),客戶端進程向服務端進程發送段文本(MySQL指令),服務器進程進行語句處理然后返回執行結果。
    的頭像 發表于 03-03 09:58 ?378次閱讀
    <b class='flag-5'>一條</b><b class='flag-5'>SQL</b><b class='flag-5'>查詢</b><b class='flag-5'>語句</b>是怎么<b class='flag-5'>去</b><b class='flag-5'>執行</b>的?(下)

    SQL語句和自定義查詢在導入包可用

    在高級任務編輯器模式下,您可以選擇要使用的操作-自己鍵入和編輯任何復雜性的SQL語句執行命令)或通過我們的可視化查詢構建器(執行
    的頭像 發表于 04-16 09:13 ?1124次閱讀

    sql查詢語句大全及實例

    SQL(Structured Query Language)是種專門用于數據庫管理系統的標準交互式數據庫查詢語言。它被廣泛應用于數據庫管理和數據操作領域。在本文中,我們將為您詳細介紹SQL
    的頭像 發表于 11-17 15:06 ?1427次閱讀

    sql where條件的執行順序

    。 在深入討論WHERE條件的執行順序之前,先回顧一下一SQL語句執行順序。一條
    的頭像 發表于 11-23 11:31 ?2145次閱讀

    oracle執行sql查詢語句的步驟是什么

    Oracle數據庫是種常用的關系型數據庫管理系統,具有強大的SQL查詢功能。Oracle執行SQL查詢
    的頭像 發表于 12-06 10:49 ?898次閱讀

    MySQL執行過程:如何進行sql 優化

    (1)客戶端發送一條查詢語句到服務器; (2)服務器先查詢緩存,如果命中緩存,則立即返回存儲在緩存的數據; (3)未命中緩存后,MySQL
    的頭像 發表于 12-12 10:19 ?383次閱讀
    MySQL<b class='flag-5'>執行</b>過程:如何進行<b class='flag-5'>sql</b> 優化

    查詢SQL在mysql內部是如何執行

    我們知道在mySQL客戶端,輸入一條查詢SQL,然后看到返回查詢的結果。這條查詢語句在 MySQ
    的頭像 發表于 01-22 14:53 ?535次閱讀
    <b class='flag-5'>查詢</b><b class='flag-5'>SQL</b>在mysql內部是如何<b class='flag-5'>執行</b>?