久久久久久久视色,久久电影免费精品,中文亚洲欧美乱码在线观看,在线免费播放AV片

<center id="vfaef"><input id="vfaef"><table id="vfaef"></table></input></center>

    <p id="vfaef"><kbd id="vfaef"></kbd></p>

    
    
    <pre id="vfaef"><u id="vfaef"></u></pre>

      <thead id="vfaef"><input id="vfaef"></input></thead>

    1. 站長(zhǎng)資訊網(wǎng)
      最全最豐富的資訊網(wǎng)站

      66個(gè)面試問(wèn)題,帶你梳理MySQL知識(shí)點(diǎn)!

      作為SQL Boy,基礎(chǔ)部分不會(huì)有人不會(huì)吧?面試也不怎么問(wèn),基礎(chǔ)掌握不錯(cuò)的小伙伴可以跳過(guò)這一部分。當(dāng)然,可能會(huì)現(xiàn)場(chǎng)寫(xiě)一些SQL語(yǔ)句,SQ語(yǔ)句可以通過(guò)??汀eetCode、LintCode之類(lèi)的網(wǎng)站來(lái)練習(xí)。

      1. 什么是內(nèi)連接、外連接、交叉連接、笛卡爾積呢?

      • 內(nèi)連接(inner join):取得兩張表中滿(mǎn)足存在連接匹配關(guān)系的記錄。
      • 外連接(outer join):不只取得兩張表中滿(mǎn)足存在連接匹配關(guān)系的記錄,還包括某張表(或兩張表)中不滿(mǎn)足匹配關(guān)系的記錄。
      • 交叉連接(cross join):顯示兩張表所有記錄一一對(duì)應(yīng),沒(méi)有匹配關(guān)系進(jìn)行篩選,它是笛卡爾積在SQL中的實(shí)現(xiàn),如果A表有m行,B表有n行,那么A和B交叉連接的結(jié)果就有m*n行。
      • 笛卡爾積:是數(shù)學(xué)中的一個(gè)概念,例如集合A={a,b},集合B={1,2,3},那么A✖️B={<a,o>,<a,1>,<a,2>,<b,0>,<b,1>,<b,2>,}。

      2. 那MySQL 的內(nèi)連接、左連接、右連接有有什么區(qū)別?

      MySQL的連接主要分為內(nèi)連接和外連接,外連接常用的有左連接、右連接。

      66個(gè)面試問(wèn)題,帶你梳理MySQL知識(shí)點(diǎn)!

      • inner join 內(nèi)連接,在兩張表進(jìn)行連接查詢(xún)時(shí),只保留兩張表中完全匹配的結(jié)果集
      • left join 在兩張表進(jìn)行連接查詢(xún)時(shí),會(huì)返回左表所有的行,即使在右表中沒(méi)有匹配的記錄。
      • right join 在兩張表進(jìn)行連接查詢(xún)時(shí),會(huì)返回右表所有的行,即使在左表中沒(méi)有匹配的記錄。

      3.說(shuō)一下數(shù)據(jù)庫(kù)的三大范式?

      66個(gè)面試問(wèn)題,帶你梳理MySQL知識(shí)點(diǎn)!

      • 第一范式:數(shù)據(jù)表中的每一列(每個(gè)字段)都不可以再拆分。 例如用戶(hù)表,用戶(hù)地址還可以拆分成國(guó)家、省份、市,這樣才是符合第一范式的。
      • 第二范式:在第一范式的基礎(chǔ)上,非主鍵列完全依賴(lài)于主鍵,而不能是依賴(lài)于主鍵的一部分。 例如訂單表里,存儲(chǔ)了商品信息(商品價(jià)格、商品類(lèi)型),那就需要把商品ID和訂單ID作為聯(lián)合主鍵,才滿(mǎn)足第二范式。
      • 第三范式:在滿(mǎn)足第二范式的基礎(chǔ)上,表中的非主鍵只依賴(lài)于主鍵,而不依賴(lài)于其他非主鍵。 例如訂單表,就不能存儲(chǔ)用戶(hù)信息(姓名、地址)。

      66個(gè)面試問(wèn)題,帶你梳理MySQL知識(shí)點(diǎn)!

      三大范式的作用是為了控制數(shù)據(jù)庫(kù)的冗余,是對(duì)空間的節(jié)省,實(shí)際上,一般互聯(lián)網(wǎng)公司的設(shè)計(jì)都是反范式的,通過(guò)冗余一些數(shù)據(jù),避免跨表跨庫(kù),利用空間換時(shí)間,提高性能。

      4.varchar與char的區(qū)別?

      66個(gè)面試問(wèn)題,帶你梳理MySQL知識(shí)點(diǎn)!

      char

      • char表示定長(zhǎng)字符串,長(zhǎng)度是固定的;
      • 如果插入數(shù)據(jù)的長(zhǎng)度小于char的固定長(zhǎng)度時(shí),則用空格填充;
      • 因?yàn)殚L(zhǎng)度固定,所以存取速度要比varchar快很多,甚至能快50%,但正因?yàn)槠溟L(zhǎng)度固定,所以會(huì)占據(jù)多余的空間,是空間換時(shí)間的做法;
      • 對(duì)于char來(lái)說(shuō),最多能存放的字符個(gè)數(shù)為255,和編碼無(wú)關(guān)

      varchar

      • varchar表示可變長(zhǎng)字符串,長(zhǎng)度是可變的;
      • 插入的數(shù)據(jù)是多長(zhǎng),就按照多長(zhǎng)來(lái)存儲(chǔ);
      • varchar在存取方面與char相反,它存取慢,因?yàn)殚L(zhǎng)度不固定,但正因如此,不占據(jù)多余的空間,是時(shí)間換空間的做法;
      • 對(duì)于varchar來(lái)說(shuō),最多能存放的字符個(gè)數(shù)為65532

      日常的設(shè)計(jì),對(duì)于長(zhǎng)度相對(duì)固定的字符串,可以使用char,對(duì)于長(zhǎng)度不確定的,使用varchar更合適一些。

      5.blob和text有什么區(qū)別?

      • blob用于存儲(chǔ)二進(jìn)制數(shù)據(jù),而text用于存儲(chǔ)大字符串。
      • blob沒(méi)有字符集,text有一個(gè)字符集,并且根據(jù)字符集的校對(duì)規(guī)則對(duì)值進(jìn)行排序和比較

      6.DATETIME和TIMESTAMP的異同?

      相同點(diǎn)

      1. 兩個(gè)數(shù)據(jù)類(lèi)型存儲(chǔ)時(shí)間的表現(xiàn)格式一致。均為 YYYY-MM-DD HH:MM:SS
      2. 兩個(gè)數(shù)據(jù)類(lèi)型都包含「日期」和「時(shí)間」部分。
      3. 兩個(gè)數(shù)據(jù)類(lèi)型都可以存儲(chǔ)微秒的小數(shù)秒(秒后6位小數(shù)秒)

      區(qū)別

      66個(gè)面試問(wèn)題,帶你梳理MySQL知識(shí)點(diǎn)!

      • 日期范圍:DATETIME 的日期范圍是 1000-01-01 00:00:00.0000009999-12-31 23:59:59.999999;TIMESTAMP 的時(shí)間范圍是1970-01-01 00:00:01.000000 UTC到 ``2038-01-09 03:14:07.999999 UTC

      • 存儲(chǔ)空間:DATETIME 的存儲(chǔ)空間為 8 字節(jié);TIMESTAMP 的存儲(chǔ)空間為 4 字節(jié)

      • 時(shí)區(qū)相關(guān):DATETIME 存儲(chǔ)時(shí)間與時(shí)區(qū)無(wú)關(guān);TIMESTAMP 存儲(chǔ)時(shí)間與時(shí)區(qū)有關(guān),顯示的值也依賴(lài)于時(shí)區(qū)

      • 默認(rèn)值:DATETIME 的默認(rèn)值為 null;TIMESTAMP 的字段默認(rèn)不為空(not null),默認(rèn)值為當(dāng)前時(shí)間(CURRENT_TIMESTAMP)

      7.MySQL中 in 和 exists 的區(qū)別?

      MySQL中的in語(yǔ)句是把外表和內(nèi)表作hash 連接,而exists語(yǔ)句是對(duì)外表作loop循環(huán),每次loop循環(huán)再對(duì)內(nèi)表進(jìn)行查詢(xún)。我們可能認(rèn)為exists比in語(yǔ)句的效率要高,這種說(shuō)法其實(shí)是不準(zhǔn)確的,要區(qū)分情景:

      • 如果查詢(xún)的兩個(gè)表大小相當(dāng),那么用in和exists差別不大。

      • 如果兩個(gè)表中一個(gè)較小,一個(gè)是大表,則子查詢(xún)表大的用exists,子查詢(xún)表小的用in。

      • not in 和not exists:如果查詢(xún)語(yǔ)句使用了not in,那么內(nèi)外表都進(jìn)行全表掃描,沒(méi)有用到索引;而not extsts的子查詢(xún)依然能用到表上的索引。所以無(wú)論那個(gè)表大,用not exists都比not in要快。

      8.MySQL里記錄貨幣用什么字段類(lèi)型比較好?

      貨幣在數(shù)據(jù)庫(kù)中MySQL常用Decimal和Numric類(lèi)型表示,這兩種類(lèi)型被MySQL實(shí)現(xiàn)為同樣的類(lèi)型。他們被用于保存與貨幣有關(guān)的數(shù)據(jù)。

      例如salary DECIMAL(9,2),9(precision)代表將被用于存儲(chǔ)值的總的小數(shù)位數(shù),而2(scale)代表將被用于存儲(chǔ)小數(shù)點(diǎn)后的位數(shù)。存儲(chǔ)在salary列中的值的范圍是從-9999999.99到9999999.99。

      DECIMAL和NUMERIC值作為字符串存儲(chǔ),而不是作為二進(jìn)制浮點(diǎn)數(shù),以便保存那些值的小數(shù)精度。

      之所以不使用float或者double的原因:因?yàn)閒loat和double是以二進(jìn)制存儲(chǔ)的,所以有一定的誤差。

      9.MySQL怎么存儲(chǔ)emoji?

      MySQL可以直接使用字符串存儲(chǔ)emoji。

      但是需要注意的,utf8 編碼是不行的,MySQL中的utf8是閹割版的 utf8,它最多只用 3 個(gè)字節(jié)存儲(chǔ)字符,所以存儲(chǔ)不了表情。那該怎么辦?

      需要使用utf8mb4編碼。

      alter table blogs modify content text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci not null;

      10.drop、delete與truncate的區(qū)別?

      三者都表示刪除,但是三者有一些差別:

      delete truncate drop
      類(lèi)型 屬于DML 屬于DDL 屬于DDL
      回滾 可回滾 不可回滾 不可回滾
      刪除內(nèi)容 表結(jié)構(gòu)還在,刪除表的全部或者一部分?jǐn)?shù)據(jù)行 表結(jié)構(gòu)還在,刪除表中的所有數(shù)據(jù) 從數(shù)據(jù)庫(kù)中刪除表,所有數(shù)據(jù)行,索引和權(quán)限也會(huì)被刪除
      刪除速度 刪除速度慢,需要逐行刪除 刪除速度快 刪除速度最快

      因此,在不再需要一張表的時(shí)候,用drop;在想刪除部分?jǐn)?shù)據(jù)行時(shí)候,用delete;在保留表而刪除所有數(shù)據(jù)的時(shí)候用truncate。

      11.UNION與UNION ALL的區(qū)別?

      • 如果使用UNION ALL,不會(huì)合并重復(fù)的記錄行
      • 效率 UNION 高于 UNION ALL

      12.count(1)、count(*) 與 count(列名) 的區(qū)別?

      66個(gè)面試問(wèn)題,帶你梳理MySQL知識(shí)點(diǎn)!

      執(zhí)行效果

      • count(*)包括了所有的列,相當(dāng)于行數(shù),在統(tǒng)計(jì)結(jié)果的時(shí)候,不會(huì)忽略列值為NULL
      • count(1)包括了忽略所有列,用1代表代碼行,在統(tǒng)計(jì)結(jié)果的時(shí)候,不會(huì)忽略列值為NULL
      • count(列名)只包括列名那一列,在統(tǒng)計(jì)結(jié)果的時(shí)候,會(huì)忽略列值為空(這里的空不是只空字符串或者0,而是表示null)的計(jì)數(shù),即某個(gè)字段值為NULL時(shí),不統(tǒng)計(jì)。

      執(zhí)行速度

      • 列名為主鍵,count(列名)會(huì)比count(1)快
      • 列名不為主鍵,count(1)會(huì)比count(列名)快
      • 如果表多個(gè)列并且沒(méi)有主鍵,則 count(1) 的執(zhí)行效率優(yōu)于 count(*)
      • 如果有主鍵,則 select count(主鍵)的執(zhí)行效率是最優(yōu)的
      • 如果表只有一個(gè)字段,則 select count(*)最優(yōu)。

      13.一條SQL查詢(xún)語(yǔ)句的執(zhí)行順序?

      66個(gè)面試問(wèn)題,帶你梳理MySQL知識(shí)點(diǎn)!

      • FROM:對(duì)FROM子句中的左表<left_table>和右表<right_table>執(zhí)行笛卡兒積(Cartesianproduct),產(chǎn)生虛擬表VT1

      • ON:對(duì)虛擬表VT1應(yīng)用ON篩選,只有那些符合<join_condition>的行才被插入虛擬表VT2中

      • JOIN:如果指定了OUTER JOIN(如LEFT OUTER JOIN、RIGHT OUTER JOIN),那么保留表中未匹配的行作為外部行添加到虛擬表VT2中,產(chǎn)生虛擬表VT3。如果FROM子句包含兩個(gè)以上表,則對(duì)上一個(gè)連接生成的結(jié)果表VT3和下一個(gè)表重復(fù)執(zhí)行步驟1)~步驟3),直到處理完所有的表為止

      • WHERE:對(duì)虛擬表VT3應(yīng)用WHERE過(guò)濾條件,只有符合<where_condition>的記錄才被插入虛擬表VT4中

      • GROUP BY:根據(jù)GROUP BY子句中的列,對(duì)VT4中的記錄進(jìn)行分組操作,產(chǎn)生VT5

      • CUBE|ROLLUP:對(duì)表VT5進(jìn)行CUBE或ROLLUP操作,產(chǎn)生表VT6

      • HAVING:對(duì)虛擬表VT6應(yīng)用HAVING過(guò)濾器,只有符合<having_condition>的記錄才被插入虛擬表VT7中。

      • SELECT:第二次執(zhí)行SELECT操作,選擇指定的列,插入到虛擬表VT8中

      • DISTINCT:去除重復(fù)數(shù)據(jù),產(chǎn)生虛擬表VT9

      • ORDER BY:將虛擬表VT9中的記錄按照<order_by_list>進(jìn)行排序操作,產(chǎn)生虛擬表VT10。11)

      • LIMIT:取出指定行的記錄,產(chǎn)生虛擬表VT11,并返回給查詢(xún)用戶(hù)

      數(shù)據(jù)庫(kù)架構(gòu)

      14.說(shuō)說(shuō) MySQL 的基礎(chǔ)架構(gòu)?

      66個(gè)面試問(wèn)題,帶你梳理MySQL知識(shí)點(diǎn)!

      MySQL邏輯架構(gòu)圖主要分三層:

      • 客戶(hù)端:最上層的服務(wù)并不是MySQL所獨(dú)有的,大多數(shù)基于網(wǎng)絡(luò)的客戶(hù)端/服務(wù)器的工具或者服務(wù)都有類(lèi)似的架構(gòu)。比如連接處理、授權(quán)認(rèn)證、安全等等。
      • Server層:大多數(shù)MySQL的核心服務(wù)功能都在這一層,包括查詢(xún)解析、分析、優(yōu)化、緩存以及所有的內(nèi)置函數(shù)(例如,日期、時(shí)間、數(shù)學(xué)和加密函數(shù)),所有跨存儲(chǔ)引擎的功能都在這一層實(shí)現(xiàn):存儲(chǔ)過(guò)程、觸發(fā)器、視圖等。
      • 存儲(chǔ)引擎層:第三層包含了存儲(chǔ)引擎。存儲(chǔ)引擎負(fù)責(zé)MySQL中數(shù)據(jù)的存儲(chǔ)和提取。Server層通過(guò)API與存儲(chǔ)引擎進(jìn)行通信。這些接口屏蔽了不同存儲(chǔ)引擎之間的差異,使得這些差異對(duì)上層的查詢(xún)過(guò)程透明。

      15.一條 SQL 查詢(xún)語(yǔ)句在 MySQL 中如何執(zhí)行的?

      • 先檢查該語(yǔ)句是否有權(quán)限,如果沒(méi)有權(quán)限,直接返回錯(cuò)誤信息,如果有權(quán)限會(huì)先查詢(xún)緩存 (MySQL8.0 版本以前)。
      • 如果沒(méi)有緩存,分析器進(jìn)行語(yǔ)法分析,提取 sql 語(yǔ)句中 select 等關(guān)鍵元素,然后判斷 sql 語(yǔ)句是否有語(yǔ)法錯(cuò)誤,比如關(guān)鍵詞是否正確等等。
      • 語(yǔ)法解析之后,MySQL的服務(wù)器會(huì)對(duì)查詢(xún)的語(yǔ)句進(jìn)行優(yōu)化,確定執(zhí)行的方案。
      • 完成查詢(xún)優(yōu)化后,按照生成的執(zhí)行計(jì)劃調(diào)用數(shù)據(jù)庫(kù)引擎接口,返回執(zhí)行結(jié)果。

      存儲(chǔ)引擎

      16.MySQL有哪些常見(jiàn)存儲(chǔ)引擎?

      66個(gè)面試問(wèn)題,帶你梳理MySQL知識(shí)點(diǎn)!

      主要存儲(chǔ)引擎以及功能如下:

      功能 MylSAM MEMORY InnoDB
      存儲(chǔ)限制 256TB RAM 64TB
      支持事務(wù) No No Yes
      支持全文索引 Yes No Yes
      支持樹(shù)索引 Yes Yes Yes
      支持哈希索引 No Yes Yes
      支持?jǐn)?shù)據(jù)緩存 No N/A Yes
      支持外鍵 No No Yes

      MySQL5.5之前,默認(rèn)存儲(chǔ)引擎是MylSAM,5.5之后變成了InnoDB。

      InnoDB支持的哈希索引是自適應(yīng)的,InnoDB會(huì)根據(jù)表的使用情況自動(dòng)為表生成哈希索引,不能人為干預(yù)是否在一張表中生成哈希索引。

      MySQL 5.6開(kāi)始InnoDB支持全文索引。

      17.那存儲(chǔ)引擎應(yīng)該怎么選擇?

      大致上可以這么選擇:

      • 大多數(shù)情況下,使用默認(rèn)的InnoDB就夠了。如果要提供提交、回滾和恢復(fù)的事務(wù)安全(ACID 兼容)能力,并要求實(shí)現(xiàn)并發(fā)控制,InnoDB 就是比較靠前的選擇了。
      • 如果數(shù)據(jù)表主要用來(lái)插入和查詢(xún)記錄,則 MyISAM 引擎提供較高的處理效率。
      • 如果只是臨時(shí)存放數(shù)據(jù),數(shù)據(jù)量不大,并且不需要較高的數(shù)據(jù)安全性,可以選擇將數(shù)據(jù)保存在內(nèi)存的 MEMORY 引擎中,MySQL 中使用該引擎作為臨時(shí)表,存放查詢(xún)的中間結(jié)果。

      使用哪一種引擎可以根據(jù)需要靈活選擇,因?yàn)榇鎯?chǔ)引擎是基于表的,所以一個(gè)數(shù)據(jù)庫(kù)中多個(gè)表可以使用不同的引擎以滿(mǎn)足各種性能和實(shí)際需求。使用合適的存儲(chǔ)引擎將會(huì)提高整個(gè)數(shù)據(jù)庫(kù)的性能。

      18.InnoDB和MylSAM主要有什么區(qū)別?

      PS:MySQL8.0都開(kāi)始慢慢流行了,如果不是面試,MylSAM其實(shí)可以不用怎么了解。

      66個(gè)面試問(wèn)題,帶你梳理MySQL知識(shí)點(diǎn)!

      1. 存儲(chǔ)結(jié)構(gòu):每個(gè)MyISAM在磁盤(pán)上存儲(chǔ)成三個(gè)文件;InnoDB所有的表都保存在同一個(gè)數(shù)據(jù)文件中(也可能是多個(gè)文件,或者是獨(dú)立的表空間文件),InnoDB表的大小只受限于操作系統(tǒng)文件的大小,一般為2GB。

      2. 事務(wù)支持:MyISAM不提供事務(wù)支持;InnoDB提供事務(wù)支持事務(wù),具有事務(wù)(commit)、回滾(rollback)和崩潰修復(fù)能力(crash recovery capabilities)的事務(wù)安全特性。

      3 最小鎖粒度:MyISAM只支持表級(jí)鎖,更新時(shí)會(huì)鎖住整張表,導(dǎo)致其它查詢(xún)和更新都會(huì)被阻塞InnoDB支持行級(jí)鎖。

      4. 索引類(lèi)型:MyISAM的索引為聚簇索引,數(shù)據(jù)結(jié)構(gòu)是B樹(shù);InnoDB的索引是非聚簇索引,數(shù)據(jù)結(jié)構(gòu)是B+樹(shù)。

      5. 主鍵必需:MyISAM允許沒(méi)有任何索引和主鍵的表存在;InnoDB如果沒(méi)有設(shè)定主鍵或者非空唯一索引,就會(huì)自動(dòng)生成一個(gè)6字節(jié)的主鍵(用戶(hù)不可見(jiàn)) ,數(shù)據(jù)是主索引的一部分,附加索引保存的是主索引的值。

      6. 表的具體行數(shù):MyISAM保存了表的總行數(shù),如果select count() from table;會(huì)直接取出出該值; InnoDB沒(méi)有保存表的總行數(shù),如果使用select count() from table;就會(huì)遍歷整個(gè)表;但是在加了wehre條件后,MyISAM和InnoDB處理的方式都一樣。

      7. 外鍵支持:MyISAM不支持外鍵;InnoDB支持外鍵。

      日志

      19.MySQL日志文件有哪些?分別介紹下作用?

      66個(gè)面試問(wèn)題,帶你梳理MySQL知識(shí)點(diǎn)!

      MySQL日志文件有很多,包括 :

      • 錯(cuò)誤日志(error log):錯(cuò)誤日志文件對(duì)MySQL的啟動(dòng)、運(yùn)行、關(guān)閉過(guò)程進(jìn)行了記錄,能幫助定位MySQL問(wèn)題。
      • 慢查詢(xún)?nèi)罩?/strong>(slow query log):慢查詢(xún)?nèi)罩臼怯脕?lái)記錄執(zhí)行時(shí)間超過(guò) long_query_time 這個(gè)變量定義的時(shí)長(zhǎng)的查詢(xún)語(yǔ)句。通過(guò)慢查詢(xún)?nèi)罩?,可以查找出哪些查?xún)語(yǔ)句的執(zhí)行效率很低,以便進(jìn)行優(yōu)化。
      • 一般查詢(xún)?nèi)罩?/strong>(general log):一般查詢(xún)?nèi)罩居涗浟怂袑?duì)MySQL數(shù)據(jù)庫(kù)請(qǐng)求的信息,無(wú)論請(qǐng)求是否正確執(zhí)行。
      • 二進(jìn)制日志(bin log):關(guān)于二進(jìn)制日志,它記錄了數(shù)據(jù)庫(kù)所有執(zhí)行的DDL和DML語(yǔ)句(除了數(shù)據(jù)查詢(xún)語(yǔ)句select、show等),以事件形式記錄并保存在二進(jìn)制文件中。

      還有兩個(gè)InnoDB存儲(chǔ)引擎特有的日志文件:

      • 重做日志(redo log):重做日志至關(guān)重要,因?yàn)樗鼈冇涗浟藢?duì)于InnoDB存儲(chǔ)引擎的事務(wù)日志。
      • 回滾日志(undo log):回滾日志同樣也是InnoDB引擎提供的日志,顧名思義,回滾日志的作用就是對(duì)數(shù)據(jù)進(jìn)行回滾。當(dāng)事務(wù)對(duì)數(shù)據(jù)庫(kù)進(jìn)行修改,InnoDB引擎不僅會(huì)記錄redo log,還會(huì)生成對(duì)應(yīng)的undo log日志;如果事務(wù)執(zhí)行失敗或調(diào)用了rollback,導(dǎo)致事務(wù)需要回滾,就可以利用undo log中的信息將數(shù)據(jù)回滾到修改之前的樣子。

      20.binlog和redo log有什么區(qū)別?

      • bin log會(huì)記錄所有與數(shù)據(jù)庫(kù)有關(guān)的日志記錄,包括InnoDB、MyISAM等存儲(chǔ)引擎的日志,而redo log只記InnoDB存儲(chǔ)引擎的日志。
      • 記錄的內(nèi)容不同,bin log記錄的是關(guān)于一個(gè)事務(wù)的具體操作內(nèi)容,即該日志是邏輯日志。而redo log記錄的是關(guān)于每個(gè)頁(yè)(Page)的更改的物理情況。
      • 寫(xiě)入的時(shí)間不同,bin log僅在事務(wù)提交前進(jìn)行提交,也就是只寫(xiě)磁盤(pán)一次。而在事務(wù)進(jìn)行的過(guò)程中,卻不斷有redo ertry被寫(xiě)入redo log中。
      • 寫(xiě)入的方式也不相同,redo log是循環(huán)寫(xiě)入和擦除,bin log是追加寫(xiě)入,不會(huì)覆蓋已經(jīng)寫(xiě)的文件。

      21.一條更新語(yǔ)句怎么執(zhí)行的了解嗎?

      更新語(yǔ)句的執(zhí)行是Server層和引擎層配合完成,數(shù)據(jù)除了要寫(xiě)入表中,還要記錄相應(yīng)的日志。

      66個(gè)面試問(wèn)題,帶你梳理MySQL知識(shí)點(diǎn)!

      • 執(zhí)行器先找引擎獲取ID=2這一行。ID是主鍵,存儲(chǔ)引擎檢索數(shù)據(jù),找到這一行。如果ID=2這一行所在的數(shù)據(jù)頁(yè)本來(lái)就在內(nèi)存中,就直接返回給執(zhí)行器;否則,需要先從磁盤(pán)讀入內(nèi)存,然后再返回。

      • 執(zhí)行器拿到引擎給的行數(shù)據(jù),把這個(gè)值加上1,比如原來(lái)是N,現(xiàn)在就是N+1,得到新的一行數(shù)據(jù),再調(diào)用引擎接口寫(xiě)入這行新數(shù)據(jù)。

      • 引擎將這行新數(shù)據(jù)更新到內(nèi)存中,同時(shí)將這個(gè)更新操作記錄到redo log里面,此時(shí)redo log處于prepare狀態(tài)。然后告知執(zhí)行器執(zhí)行完成了,隨時(shí)可以提交事務(wù)。

      • 執(zhí)行器生成這個(gè)操作的binlog,并把binlog寫(xiě)入磁盤(pán)。

      • 執(zhí)行器調(diào)用引擎的提交事務(wù)接口,引擎把剛剛寫(xiě)入的redo log改成提交(commit)狀態(tài),更新完成。

      從上圖可以看出,MySQL在執(zhí)行更新語(yǔ)句的時(shí)候,在服務(wù)層進(jìn)行語(yǔ)句的解析和執(zhí)行,在引擎層進(jìn)行數(shù)據(jù)的提取和存儲(chǔ);同時(shí)在服務(wù)層對(duì)binlog進(jìn)行寫(xiě)入,在InnoDB內(nèi)進(jìn)行redo log的寫(xiě)入。

      不僅如此,在對(duì)redo log寫(xiě)入時(shí)有兩個(gè)階段的提交,一是binlog寫(xiě)入之前prepare狀態(tài)的寫(xiě)入,二是binlog寫(xiě)入之后commit狀態(tài)的寫(xiě)入。

      22.那為什么要兩階段提交呢?

      為什么要兩階段提交呢?直接提交不行嗎?

      我們可以假設(shè)不采用兩階段提交的方式,而是采用“單階段”進(jìn)行提交,即要么先寫(xiě)入redo log,后寫(xiě)入binlog;要么先寫(xiě)入binlog,后寫(xiě)入redo log。這兩種方式的提交都會(huì)導(dǎo)致原先數(shù)據(jù)庫(kù)的狀態(tài)和被恢復(fù)后的數(shù)據(jù)庫(kù)的狀態(tài)不一致。

      先寫(xiě)入redo log,后寫(xiě)入binlog:

      在寫(xiě)完redo log之后,數(shù)據(jù)此時(shí)具有crash-safe能力,因此系統(tǒng)崩潰,數(shù)據(jù)會(huì)恢復(fù)成事務(wù)開(kāi)始之前的狀態(tài)。但是,若在redo log寫(xiě)完時(shí)候,binlog寫(xiě)入之前,系統(tǒng)發(fā)生了宕機(jī)。此時(shí)binlog沒(méi)有對(duì)上面的更新語(yǔ)句進(jìn)行保存,導(dǎo)致當(dāng)使用binlog進(jìn)行數(shù)據(jù)庫(kù)的備份或者恢復(fù)時(shí),就少了上述的更新語(yǔ)句。從而使得id=2這一行的數(shù)據(jù)沒(méi)有被更新。

      66個(gè)面試問(wèn)題,帶你梳理MySQL知識(shí)點(diǎn)!

      先寫(xiě)入binlog,后寫(xiě)入redo log:

      寫(xiě)完binlog之后,所有的語(yǔ)句都被保存,所以通過(guò)binlog復(fù)制或恢復(fù)出來(lái)的數(shù)據(jù)庫(kù)中id=2這一行的數(shù)據(jù)會(huì)被更新為a=1。但是如果在redo log寫(xiě)入之前,系統(tǒng)崩潰,那么redo log中記錄的這個(gè)事務(wù)會(huì)無(wú)效,導(dǎo)致實(shí)際數(shù)據(jù)庫(kù)中id=2這一行的數(shù)據(jù)并沒(méi)有更新。

      66個(gè)面試問(wèn)題,帶你梳理MySQL知識(shí)點(diǎn)!

      簡(jiǎn)單說(shuō),redo log和binlog都可以用于表示事務(wù)的提交狀態(tài),而兩階段提交就是讓這兩個(gè)狀態(tài)保持邏輯上的一致。

      23.redo log怎么刷入磁盤(pán)的知道嗎?

      redo log的寫(xiě)入不是直接落到磁盤(pán),而是在內(nèi)存中設(shè)置了一片稱(chēng)之為redo log buffer的連續(xù)內(nèi)存空間,也就是redo 日志緩沖區(qū)。

      66個(gè)面試問(wèn)題,帶你梳理MySQL知識(shí)點(diǎn)!

      什么時(shí)候會(huì)刷入磁盤(pán)?

      在如下的一些情況中,log buffer的數(shù)據(jù)會(huì)刷入磁盤(pán):

      • log buffer 空間不足時(shí)

      log buffer 的大小是有限的,如果不停的往這個(gè)有限大小的 log buffer 里塞入日志,很快它就會(huì)被填滿(mǎn)。如果當(dāng)前寫(xiě)入 log buffer 的redo 日志量已經(jīng)占滿(mǎn)了 log buffer 總?cè)萘康拇蠹s一半左右,就需要把這些日志刷新到磁盤(pán)上。

      • 事務(wù)提交時(shí)

      在事務(wù)提交時(shí),為了保證持久性,會(huì)把log buffer中的日志全部刷到磁盤(pán)。注意,這時(shí)候,除了本事務(wù)的,可能還會(huì)刷入其它事務(wù)的日志。

      • 后臺(tái)線(xiàn)程輸入

      有一個(gè)后臺(tái)線(xiàn)程,大約每秒都會(huì)刷新一次log buffer中的redo log到磁盤(pán)。

      • 正常關(guān)閉服務(wù)器時(shí)
      • 觸發(fā)checkpoint規(guī)則

      重做日志緩存、重做日志文件都是以塊(block) 的方式進(jìn)行保存的,稱(chēng)之為重做日志塊(redo log block) ,塊的大小是固定的512字節(jié)。我們的redo log它是固定大小的,可以看作是一個(gè)邏輯上的 log group,由一定數(shù)量的log block 組成。

      66個(gè)面試問(wèn)題,帶你梳理MySQL知識(shí)點(diǎn)!

      它的寫(xiě)入方式是從頭到尾開(kāi)始寫(xiě),寫(xiě)到末尾又回到開(kāi)頭循環(huán)寫(xiě)。

      其中有兩個(gè)標(biāo)記位置:

      write pos是當(dāng)前記錄的位置,一邊寫(xiě)一邊后移,寫(xiě)到第3號(hào)文件末尾后就回到0號(hào)文件開(kāi)頭。checkpoint是當(dāng)前要擦除的位置,也是往后推移并且循環(huán)的,擦除記錄前要把記錄更新到磁盤(pán)。

      66個(gè)面試問(wèn)題,帶你梳理MySQL知識(shí)點(diǎn)!

      當(dāng)write_pos追上checkpoint時(shí),表示redo log日志已經(jīng)寫(xiě)滿(mǎn)。這時(shí)候就不能接著往里寫(xiě)數(shù)據(jù)了,需要執(zhí)行checkpoint規(guī)則騰出可寫(xiě)空間。

      所謂的checkpoint規(guī)則,就是checkpoint觸發(fā)后,將buffer中日志頁(yè)都刷到磁盤(pán)。

      SQL 優(yōu)化

      24.慢SQL如何定位呢?

      慢SQL的監(jiān)控主要通過(guò)兩個(gè)途徑:

      66個(gè)面試問(wèn)題,帶你梳理MySQL知識(shí)點(diǎn)!

      • 慢查詢(xún)?nèi)罩?/strong>:開(kāi)啟MySQL的慢查詢(xún)?nèi)罩?,再通過(guò)一些工具比如mysqldumpslow去分析對(duì)應(yīng)的慢查詢(xún)?nèi)罩荆?dāng)然現(xiàn)在一般的云廠(chǎng)商都提供了可視化的平臺(tái)。
      • 服務(wù)監(jiān)控:可以在業(yè)務(wù)的基建中加入對(duì)慢SQL的監(jiān)控,常見(jiàn)的方案有字節(jié)碼插樁、連接池?cái)U(kuò)展、ORM框架過(guò)程,對(duì)服務(wù)運(yùn)行中的慢SQL進(jìn)行監(jiān)控和告警。

      25.有哪些方式優(yōu)化慢SQL?

      慢SQL的優(yōu)化,主要從兩個(gè)方面考慮,SQL語(yǔ)句本身的優(yōu)化,以及數(shù)據(jù)庫(kù)設(shè)計(jì)的優(yōu)化。

      66個(gè)面試問(wèn)題,帶你梳理MySQL知識(shí)點(diǎn)!

      避免不必要的列

      這個(gè)是老生常談,但還是經(jīng)常會(huì)出的情況,SQL查詢(xún)的時(shí)候,應(yīng)該只查詢(xún)需要的列,而不要包含額外的列,像slect * 這種寫(xiě)法應(yīng)該盡量避免。

      分頁(yè)優(yōu)化

      在數(shù)據(jù)量比較大,分頁(yè)比較深的情況下,需要考慮分頁(yè)的優(yōu)化。

      例如:

      select * from table where type = 2 and level = 9 order by id asc limit 190289,10;

      優(yōu)化方案:

      • 延遲關(guān)聯(lián)

        先通過(guò)where條件提取出主鍵,在將該表與原數(shù)據(jù)表關(guān)聯(lián),通過(guò)主鍵id提取數(shù)據(jù)行,而不是通過(guò)原來(lái)的二級(jí)索引提取數(shù)據(jù)行

        例如:

        select a.* from table a,   (select id from table where type = 2 and level = 9 order by id asc limit 190289,10 ) b  where a.id = b.id
      • 書(shū)簽方式

        書(shū)簽方式就是找到limit第一個(gè)參數(shù)對(duì)應(yīng)的主鍵值,根據(jù)這個(gè)主鍵值再去過(guò)濾并limit

        例如:

        select * from table where id >   (select * from table where type = 2 and level = 9 order by id asc limit 190
      索引優(yōu)化

      合理地設(shè)計(jì)和使用索引,是優(yōu)化慢SQL的利器。

      利用覆蓋索引

      InnoDB使用非主鍵索引查詢(xún)數(shù)據(jù)時(shí)會(huì)回表,但是如果索引的葉節(jié)點(diǎn)中已經(jīng)包含要查詢(xún)的字段,那它沒(méi)有必要再回表查詢(xún)了,這就叫覆蓋索引

      例如對(duì)于如下查詢(xún):

      select name from test where city='上海'

      我們將被查詢(xún)的字段建立到聯(lián)合索引中,這樣查詢(xún)結(jié)果就可以直接從索引中獲取

      alter table test add index idx_city_name (city, name);

      低版本避免使用or查詢(xún)

      在 MySQL 5.0 之前的版本要盡量避免使用 or 查詢(xún),可以使用 union 或者子查詢(xún)來(lái)替代,因?yàn)樵缙诘?MySQL 版本使用 or 查詢(xún)可能會(huì)導(dǎo)致索引失效,高版本引入了索引合并,解決了這個(gè)問(wèn)題。

      避免使用 != 或者 <> 操作符

      SQL中,不等于操作符會(huì)導(dǎo)致查詢(xún)引擎放棄查詢(xún)索引,引起全表掃描,即使比較的字段上有索引

      解決方法:通過(guò)把不等于操作符改成or,可以使用索引,避免全表掃描

      例如,把column<>’aaa’,改成column>’aaa’ or column<’aaa’,就可以使用索引了

      適當(dāng)使用前綴索引

      適當(dāng)?shù)厥褂们熬Y所云,可以降低索引的空間占用,提高索引的查詢(xún)效率。

      比如,郵箱的后綴都是固定的“@xxx.com”,那么類(lèi)似這種后面幾位為固定值的字段就非常適合定義為前綴索引

      alter table test add index index2(email(6));

      PS:需要注意的是,前綴索引也存在缺點(diǎn),MySQL無(wú)法利用前綴索引做order by和group by 操作,也無(wú)法作為覆蓋索引

      避免列上函數(shù)運(yùn)算

      要避免在列字段上進(jìn)行算術(shù)運(yùn)算或其他表達(dá)式運(yùn)算,否則可能會(huì)導(dǎo)致存儲(chǔ)引擎無(wú)法正確使用索引,從而影響了查詢(xún)的效率

      select * from test where id + 1 = 50; select * from test where month(updateTime) = 7;

      正確使用聯(lián)合索引

      使用聯(lián)合索引的時(shí)候,注意最左匹配原則。

      JOIN優(yōu)化

      優(yōu)化子查詢(xún)

      盡量使用 Join 語(yǔ)句來(lái)替代子查詢(xún),因?yàn)樽硬樵?xún)是嵌套查詢(xún),而嵌套查詢(xún)會(huì)新創(chuàng)建一張臨時(shí)表,而臨時(shí)表的創(chuàng)建與銷(xiāo)毀會(huì)占用一定的系統(tǒng)資源以及花費(fèi)一定的時(shí)間,同時(shí)對(duì)于返回結(jié)果集比較大的子查詢(xún),其對(duì)查詢(xún)性能的影響更大

      小表驅(qū)動(dòng)大表

      關(guān)聯(lián)查詢(xún)的時(shí)候要拿小表去驅(qū)動(dòng)大表,因?yàn)殛P(guān)聯(lián)的時(shí)候,MySQL內(nèi)部會(huì)遍歷驅(qū)動(dòng)表,再去連接被驅(qū)動(dòng)表。

      比如left join,左表就是驅(qū)動(dòng)表,A表小于B表,建立連接的次數(shù)就少,查詢(xún)速度就被加快了。

       select name from A left join B ;

      適當(dāng)增加冗余字段

      增加冗余字段可以減少大量的連表查詢(xún),因?yàn)槎鄰埍淼倪B表查詢(xún)性能很低,所有可以適當(dāng)?shù)脑黾尤哂嘧侄危詼p少多張表的關(guān)聯(lián)查詢(xún),這是以空間換時(shí)間的優(yōu)化策略

      避免使用JOIN關(guān)聯(lián)太多的表

      《阿里巴巴Java開(kāi)發(fā)手冊(cè)》規(guī)定不要join超過(guò)三張表,第一join太多降低查詢(xún)的速度,第二join的buffer會(huì)占用

      贊(0)
      分享到: 更多 (0)
      網(wǎng)站地圖   滬ICP備18035694號(hào)-2    滬公網(wǎng)安備31011702889846號(hào)