日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > 数据库 >内容正文

数据库

MySQL数据库面试题(2020最新版)

發(fā)布時(shí)間:2023/12/10 数据库 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 MySQL数据库面试题(2020最新版) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

你是否有為快速開(kāi)發(fā)各種報(bào)表而煩惱?遇到類似如下的問(wèn)題:

  • 表格少的,可以用代碼寫,幾十上百?gòu)埍砀衲?#xff0c;純手工需要用多少時(shí)間?
  • 格式復(fù)雜,邏輯復(fù)雜的,做起來(lái)更是頭大
  • 需求總變來(lái)變?nèi)?#xff0c;修改和維護(hù)成本太高
  • 圖形自己做不美觀,而且工作量巨大
  • 用第三方的相對(duì)簡(jiǎn)單,但集成和學(xué)習(xí)成本也不小

從各行業(yè)合作伙伴的實(shí)際使用情況,證明使用下文說(shuō)的報(bào)表做表格和圖形,可以極大的提升效率,節(jié)省成本,詳情請(qǐng)查看文章:https://thinkwon.blog.csdn.net/article/details/125035932
文章干貨多多,歡迎一鍵三連,謝謝😊😊

Java面試總結(jié)(2021優(yōu)化版)已發(fā)布在個(gè)人微信公眾號(hào)【技術(shù)人成長(zhǎng)之路】,優(yōu)化版首先修正了讀者反饋的部分答案存在的錯(cuò)誤,同時(shí)根據(jù)最新面試總結(jié),刪除了低頻問(wèn)題,添加了一些常見(jiàn)面試題,對(duì)文章進(jìn)行了精簡(jiǎn)優(yōu)化,歡迎大家關(guān)注!😊😊

【技術(shù)人成長(zhǎng)之路】,助力技術(shù)人成長(zhǎng)!更多精彩文章第一時(shí)間在公眾號(hào)發(fā)布哦!

文章目錄

    • 數(shù)據(jù)庫(kù)基礎(chǔ)知識(shí)
      • 為什么要使用數(shù)據(jù)庫(kù)
      • 什么是SQL?
      • 什么是MySQL?
      • 數(shù)據(jù)庫(kù)三大范式是什么
      • mysql有關(guān)權(quán)限的表都有哪幾個(gè)
      • MySQL的binlog有有幾種錄入格式?分別有什么區(qū)別?
    • 數(shù)據(jù)類型
      • mysql有哪些數(shù)據(jù)類型
    • 引擎
      • MySQL存儲(chǔ)引擎MyISAM與InnoDB區(qū)別
      • MyISAM索引與InnoDB索引的區(qū)別?
      • InnoDB引擎的4大特性
      • 存儲(chǔ)引擎選擇
    • 索引
      • 什么是索引?
      • 索引有哪些優(yōu)缺點(diǎn)?
      • 索引使用場(chǎng)景(重點(diǎn))
      • 索引有哪幾種類型?
      • 索引的數(shù)據(jù)結(jié)構(gòu)(b樹,hash)
      • 索引的基本原理
      • 索引算法有哪些?
      • 索引設(shè)計(jì)的原則?
      • 創(chuàng)建索引的原則(重中之重)
      • 創(chuàng)建索引的三種方式,刪除索引
      • 創(chuàng)建索引時(shí)需要注意什么?
      • 使用索引查詢一定能提高查詢的性能嗎?為什么
      • 百萬(wàn)級(jí)別或以上的數(shù)據(jù)如何刪除
      • 前綴索引
      • 什么是最左前綴原則?什么是最左匹配原則
      • B樹和B+樹的區(qū)別
      • 使用B樹的好處
      • 使用B+樹的好處
      • Hash索引和B+樹所有有什么區(qū)別或者說(shuō)優(yōu)劣呢?
      • 數(shù)據(jù)庫(kù)為什么使用B+樹而不是B樹
      • B+樹在滿足聚簇索引和覆蓋索引的時(shí)候不需要回表查詢數(shù)據(jù),
      • 什么是聚簇索引?何時(shí)使用聚簇索引與非聚簇索引
      • 非聚簇索引一定會(huì)回表查詢嗎?
      • 聯(lián)合索引是什么?為什么需要注意聯(lián)合索引中的順序?
    • 事務(wù)
      • 什么是數(shù)據(jù)庫(kù)事務(wù)?
      • 事物的四大特性(ACID)介紹一下?
      • 什么是臟讀?幻讀?不可重復(fù)讀?
      • 什么是事務(wù)的隔離級(jí)別?MySQL的默認(rèn)隔離級(jí)別是什么?
      • 對(duì)MySQL的鎖了解嗎
      • 隔離級(jí)別與鎖的關(guān)系
      • 按照鎖的粒度分?jǐn)?shù)據(jù)庫(kù)鎖有哪些?鎖機(jī)制與InnoDB鎖算法
      • 從鎖的類別上分MySQL都有哪些鎖呢?像上面那樣子進(jìn)行鎖定豈不是有點(diǎn)阻礙并發(fā)效率了
      • MySQL中InnoDB引擎的行鎖是怎么實(shí)現(xiàn)的?
      • InnoDB存儲(chǔ)引擎的鎖的算法有三種
      • 什么是死鎖?怎么解決?
      • 數(shù)據(jù)庫(kù)的樂(lè)觀鎖和悲觀鎖是什么?怎么實(shí)現(xiàn)的?
    • 視圖
      • 為什么要使用視圖?什么是視圖?
      • 視圖有哪些特點(diǎn)?
      • 視圖的使用場(chǎng)景有哪些?
      • 視圖的優(yōu)點(diǎn)
      • 視圖的缺點(diǎn)
      • 什么是游標(biāo)?
    • 存儲(chǔ)過(guò)程與函數(shù)
      • 什么是存儲(chǔ)過(guò)程?有哪些優(yōu)缺點(diǎn)?
    • 觸發(fā)器
      • 什么是觸發(fā)器?觸發(fā)器的使用場(chǎng)景有哪些?
      • MySQL中都有哪些觸發(fā)器?
    • 常用SQL語(yǔ)句
      • SQL語(yǔ)句主要分為哪幾類
      • 超鍵、候選鍵、主鍵、外鍵分別是什么?
      • SQL 約束有哪幾種?
      • 六種關(guān)聯(lián)查詢
      • 什么是子查詢
      • 子查詢的三種情況
      • mysql中 in 和 exists 區(qū)別
      • varchar與char的區(qū)別
      • varchar(50)中50的涵義
      • int(20)中20的涵義
      • mysql為什么這么設(shè)計(jì)
      • mysql中int(10)和char(10)以及varchar(10)的區(qū)別
      • FLOAT和DOUBLE的區(qū)別是什么?
      • drop、delete與truncate的區(qū)別
      • UNION與UNION ALL的區(qū)別?
    • SQL優(yōu)化
      • 如何定位及優(yōu)化SQL語(yǔ)句的性能問(wèn)題?創(chuàng)建的索引有沒(méi)有被使用到?或者說(shuō)怎么才可以知道這條語(yǔ)句運(yùn)行很慢的原因?
      • SQL的生命周期?
      • 大表數(shù)據(jù)查詢,怎么優(yōu)化
      • 超大分頁(yè)怎么處理?
      • mysql 分頁(yè)
      • 慢查詢?nèi)罩?/li>
      • 關(guān)心過(guò)業(yè)務(wù)系統(tǒng)里面的sql耗時(shí)嗎?統(tǒng)計(jì)過(guò)慢查詢嗎?對(duì)慢查詢都怎么優(yōu)化過(guò)?
      • 為什么要盡量設(shè)定一個(gè)主鍵?
      • 主鍵使用自增ID還是UUID?
      • 字段為什么要求定義為not null?
      • 如果要存儲(chǔ)用戶的密碼散列,應(yīng)該使用什么字段進(jìn)行存儲(chǔ)?
      • 優(yōu)化查詢過(guò)程中的數(shù)據(jù)訪問(wèn)
      • 優(yōu)化長(zhǎng)難的查詢語(yǔ)句
      • 優(yōu)化特定類型的查詢語(yǔ)句
      • 優(yōu)化關(guān)聯(lián)查詢
      • 優(yōu)化子查詢
      • 優(yōu)化LIMIT分頁(yè)
      • 優(yōu)化UNION查詢
      • 優(yōu)化WHERE子句
    • 數(shù)據(jù)庫(kù)優(yōu)化
      • 為什么要優(yōu)化
      • 數(shù)據(jù)庫(kù)結(jié)構(gòu)優(yōu)化
      • MySQL數(shù)據(jù)庫(kù)cpu飆升到500%的話他怎么處理?
      • 大表怎么優(yōu)化?某個(gè)表有近千萬(wàn)數(shù)據(jù),CRUD比較慢,如何優(yōu)化?分庫(kù)分表了是怎么做的?分表分庫(kù)了有什么問(wèn)題?有用到中間件么?他們的原理知道么?
        • 垂直分表
          • 適用場(chǎng)景
          • 缺點(diǎn)
        • 水平分表:
          • 適用場(chǎng)景
          • 水平切分的缺點(diǎn)
      • MySQL的復(fù)制原理以及流程
      • 讀寫分離有哪些解決方案?
      • 備份計(jì)劃,mysqldump以及xtranbackup的實(shí)現(xiàn)原理
      • 數(shù)據(jù)表?yè)p壞的修復(fù)方式有哪些?

Java面試總結(jié)匯總,整理了包括Java基礎(chǔ)知識(shí),集合容器,并發(fā)編程,JVM,常用開(kāi)源框架Spring,MyBatis,數(shù)據(jù)庫(kù),中間件等,包含了作為一個(gè)Java工程師在面試中需要用到或者可能用到的絕大部分知識(shí)。歡迎大家閱讀,本人見(jiàn)識(shí)有限,寫的博客難免有錯(cuò)誤或者疏忽的地方,還望各位大佬指點(diǎn),在此表示感激不盡。文章持續(xù)更新中…

序號(hào)內(nèi)容鏈接地址
1Java基礎(chǔ)知識(shí)面試題(2020最新版)https://thinkwon.blog.csdn.net/article/details/104390612
2Java集合容器面試題(2020最新版)https://thinkwon.blog.csdn.net/article/details/104588551
3Java異常面試題(2020最新版)https://thinkwon.blog.csdn.net/article/details/104390689
4并發(fā)編程面試題(2020最新版)https://thinkwon.blog.csdn.net/article/details/104863992
5JVM面試題(2020最新版)https://thinkwon.blog.csdn.net/article/details/104390752
6Spring面試題(2020最新版)https://thinkwon.blog.csdn.net/article/details/104397516
7Spring MVC面試題(2020最新版)https://thinkwon.blog.csdn.net/article/details/104397427
8Spring Boot面試題(2020最新版)https://thinkwon.blog.csdn.net/article/details/104397299
9Spring Cloud面試題(2020最新版)https://thinkwon.blog.csdn.net/article/details/104397367
10MyBatis面試題(2020最新版)https://thinkwon.blog.csdn.net/article/details/101292950
11Redis面試題(2020最新版)https://thinkwon.blog.csdn.net/article/details/103522351
12MySQL數(shù)據(jù)庫(kù)面試題(2020最新版)https://thinkwon.blog.csdn.net/article/details/104778621
13消息中間件MQ與RabbitMQ面試題(2020最新版)https://thinkwon.blog.csdn.net/article/details/104588612
14Dubbo面試題(2020最新版)https://thinkwon.blog.csdn.net/article/details/104390006
15Linux面試題(2020最新版)https://thinkwon.blog.csdn.net/article/details/104588679
16Tomcat面試題(2020最新版)https://thinkwon.blog.csdn.net/article/details/104397665
17ZooKeeper面試題(2020最新版)https://thinkwon.blog.csdn.net/article/details/104397719
18Netty面試題(2020最新版)https://thinkwon.blog.csdn.net/article/details/104391081
19架構(gòu)設(shè)計(jì)&分布式&數(shù)據(jù)結(jié)構(gòu)與算法面試題(2020最新版)https://thinkwon.blog.csdn.net/article/details/105870730

數(shù)據(jù)庫(kù)基礎(chǔ)知識(shí)

為什么要使用數(shù)據(jù)庫(kù)

數(shù)據(jù)保存在內(nèi)存

優(yōu)點(diǎn): 存取速度快

缺點(diǎn): 數(shù)據(jù)不能永久保存

數(shù)據(jù)保存在文件

優(yōu)點(diǎn): 數(shù)據(jù)永久保存

缺點(diǎn):1)速度比內(nèi)存操作慢,頻繁的IO操作。2)查詢數(shù)據(jù)不方便

數(shù)據(jù)保存在數(shù)據(jù)庫(kù)

1)數(shù)據(jù)永久保存

2)使用SQL語(yǔ)句,查詢方便效率高。

3)管理數(shù)據(jù)方便

什么是SQL?

結(jié)構(gòu)化查詢語(yǔ)言(Structured Query Language)簡(jiǎn)稱SQL,是一種數(shù)據(jù)庫(kù)查詢語(yǔ)言。

作用:用于存取數(shù)據(jù)、查詢、更新和管理關(guān)系數(shù)據(jù)庫(kù)系統(tǒng)。

什么是MySQL?

MySQL是一個(gè)關(guān)系型數(shù)據(jù)庫(kù)管理系統(tǒng),由瑞典MySQL AB 公司開(kāi)發(fā),屬于 Oracle 旗下產(chǎn)品。MySQL 是最流行的關(guān)系型數(shù)據(jù)庫(kù)管理系統(tǒng)之一,在 WEB 應(yīng)用方面,MySQL是最好的 RDBMS (Relational Database Management System,關(guān)系數(shù)據(jù)庫(kù)管理系統(tǒng)) 應(yīng)用軟件之一。在Java企業(yè)級(jí)開(kāi)發(fā)中非常常用,因?yàn)?MySQL 是開(kāi)源免費(fèi)的,并且方便擴(kuò)展。

數(shù)據(jù)庫(kù)三大范式是什么

第一范式:每個(gè)列都不可以再拆分。

第二范式:在第一范式的基礎(chǔ)上,非主鍵列完全依賴于主鍵,而不能是依賴于主鍵的一部分。

第三范式:在第二范式的基礎(chǔ)上,非主鍵列只依賴于主鍵,不依賴于其他非主鍵。

在設(shè)計(jì)數(shù)據(jù)庫(kù)結(jié)構(gòu)的時(shí)候,要盡量遵守三范式,如果不遵守,必須有足夠的理由。比如性能。事實(shí)上我們經(jīng)常會(huì)為了性能而妥協(xié)數(shù)據(jù)庫(kù)的設(shè)計(jì)。

mysql有關(guān)權(quán)限的表都有哪幾個(gè)

MySQL服務(wù)器通過(guò)權(quán)限表來(lái)控制用戶對(duì)數(shù)據(jù)庫(kù)的訪問(wèn),權(quán)限表存放在mysql數(shù)據(jù)庫(kù)里,由mysql_install_db腳本初始化。這些權(quán)限表分別user,db,table_priv,columns_priv和host。下面分別介紹一下這些表的結(jié)構(gòu)和內(nèi)容:

  • user權(quán)限表:記錄允許連接到服務(wù)器的用戶帳號(hào)信息,里面的權(quán)限是全局級(jí)的。
  • db權(quán)限表:記錄各個(gè)帳號(hào)在各個(gè)數(shù)據(jù)庫(kù)上的操作權(quán)限。
  • table_priv權(quán)限表:記錄數(shù)據(jù)表級(jí)的操作權(quán)限。
  • columns_priv權(quán)限表:記錄數(shù)據(jù)列級(jí)的操作權(quán)限。
  • host權(quán)限表:配合db權(quán)限表對(duì)給定主機(jī)上數(shù)據(jù)庫(kù)級(jí)操作權(quán)限作更細(xì)致的控制。這個(gè)權(quán)限表不受GRANT和REVOKE語(yǔ)句的影響。

MySQL的binlog有有幾種錄入格式?分別有什么區(qū)別?

有三種格式,statement,row和mixed。

  • statement模式下,每一條會(huì)修改數(shù)據(jù)的sql都會(huì)記錄在binlog中。不需要記錄每一行的變化,減少了binlog日志量,節(jié)約了IO,提高性能。由于sql的執(zhí)行是有上下文的,因此在保存的時(shí)候需要保存相關(guān)的信息,同時(shí)還有一些使用了函數(shù)之類的語(yǔ)句無(wú)法被記錄復(fù)制。
  • row級(jí)別下,不記錄sql語(yǔ)句上下文相關(guān)信息,僅保存哪條記錄被修改。記錄單元為每一行的改動(dòng),基本是可以全部記下來(lái)但是由于很多操作,會(huì)導(dǎo)致大量行的改動(dòng)(比如alter table),因此這種模式的文件保存的信息太多,日志量太大。
  • mixed,一種折中的方案,普通操作使用statement記錄,當(dāng)無(wú)法使用statement的時(shí)候使用row。

此外,新版的MySQL中對(duì)row級(jí)別也做了一些優(yōu)化,當(dāng)表結(jié)構(gòu)發(fā)生變化的時(shí)候,會(huì)記錄語(yǔ)句而不是逐行記錄。

數(shù)據(jù)類型

mysql有哪些數(shù)據(jù)類型

分類類型名稱說(shuō)明
整數(shù)類型tinyInt很小的整數(shù)(8位二進(jìn)制)
smallint小的整數(shù)(16位二進(jìn)制)
mediumint中等大小的整數(shù)(24位二進(jìn)制)
int(integer)普通大小的整數(shù)(32位二進(jìn)制)
小數(shù)類型float單精度浮點(diǎn)數(shù)
double雙精度浮點(diǎn)數(shù)
decimal(m,d)壓縮嚴(yán)格的定點(diǎn)數(shù)
日期類型yearYYYY 1901~2155
timeHH:MM:SS -838:59:59~838:59:59
dateYYYY-MM-DD 1000-01-01~9999-12-3
datetimeYYYY-MM-DD HH:MM:SS 1000-01-01 00:00:00~ 9999-12-31 23:59:59
timestampYYYY-MM-DD HH:MM:SS 19700101 00:00:01 UTC~2038-01-19 03:14:07UTC
文本、二進(jìn)制類型CHAR(M)M為0~255之間的整數(shù)
VARCHAR(M)M為0~65535之間的整數(shù)
TINYBLOB允許長(zhǎng)度0~255字節(jié)
BLOB允許長(zhǎng)度0~65535字節(jié)
MEDIUMBLOB允許長(zhǎng)度0~167772150字節(jié)
LONGBLOB允許長(zhǎng)度0~4294967295字節(jié)
TINYTEXT允許長(zhǎng)度0~255字節(jié)
TEXT允許長(zhǎng)度0~65535字節(jié)
MEDIUMTEXT允許長(zhǎng)度0~167772150字節(jié)
LONGTEXT允許長(zhǎng)度0~4294967295字節(jié)
VARBINARY(M)允許長(zhǎng)度0~M個(gè)字節(jié)的變長(zhǎng)字節(jié)字符串
BINARY(M)允許長(zhǎng)度0~M個(gè)字節(jié)的定長(zhǎng)字節(jié)字符串
  • 1、整數(shù)類型,包括TINYINT、SMALLINT、MEDIUMINT、INT、BIGINT,分別表示1字節(jié)、2字節(jié)、3字節(jié)、4字節(jié)、8字節(jié)整數(shù)。任何整數(shù)類型都可以加上UNSIGNED屬性,表示數(shù)據(jù)是無(wú)符號(hào)的,即非負(fù)整數(shù)。
    長(zhǎng)度:整數(shù)類型可以被指定長(zhǎng)度,例如:INT(11)表示長(zhǎng)度為11的INT類型。長(zhǎng)度在大多數(shù)場(chǎng)景是沒(méi)有意義的,它不會(huì)限制值的合法范圍,只會(huì)影響顯示字符的個(gè)數(shù),而且需要和UNSIGNED ZEROFILL屬性配合使用才有意義。
    例子,假定類型設(shè)定為INT(5),屬性為UNSIGNED ZEROFILL,如果用戶插入的數(shù)據(jù)為12的話,那么數(shù)據(jù)庫(kù)實(shí)際存儲(chǔ)數(shù)據(jù)為00012。

  • 2、實(shí)數(shù)類型,包括FLOAT、DOUBLE、DECIMAL。
    DECIMAL可以用于存儲(chǔ)比BIGINT還大的整型,能存儲(chǔ)精確的小數(shù)。
    而FLOAT和DOUBLE是有取值范圍的,并支持使用標(biāo)準(zhǔn)的浮點(diǎn)進(jìn)行近似計(jì)算。
    計(jì)算時(shí)FLOAT和DOUBLE相比DECIMAL效率更高一些,DECIMAL你可以理解成是用字符串進(jìn)行處理。

  • 3、字符串類型,包括VARCHAR、CHAR、TEXT、BLOB
    VARCHAR用于存儲(chǔ)可變長(zhǎng)字符串,它比定長(zhǎng)類型更節(jié)省空間。
    VARCHAR使用額外1或2個(gè)字節(jié)存儲(chǔ)字符串長(zhǎng)度。列長(zhǎng)度小于255字節(jié)時(shí),使用1字節(jié)表示,否則使用2字節(jié)表示。
    VARCHAR存儲(chǔ)的內(nèi)容超出設(shè)置的長(zhǎng)度時(shí),內(nèi)容會(huì)被截?cái)唷?br /> CHAR是定長(zhǎng)的,根據(jù)定義的字符串長(zhǎng)度分配足夠的空間。
    CHAR會(huì)根據(jù)需要使用空格進(jìn)行填充方便比較。
    CHAR適合存儲(chǔ)很短的字符串,或者所有值都接近同一個(gè)長(zhǎng)度。
    CHAR存儲(chǔ)的內(nèi)容超出設(shè)置的長(zhǎng)度時(shí),內(nèi)容同樣會(huì)被截?cái)唷?/p>

    使用策略:
    對(duì)于經(jīng)常變更的數(shù)據(jù)來(lái)說(shuō),CHAR比VARCHAR更好,因?yàn)镃HAR不容易產(chǎn)生碎片。
    對(duì)于非常短的列,CHAR比VARCHAR在存儲(chǔ)空間上更有效率。
    使用時(shí)要注意只分配需要的空間,更長(zhǎng)的列排序時(shí)會(huì)消耗更多內(nèi)存。
    盡量避免使用TEXT/BLOB類型,查詢時(shí)會(huì)使用臨時(shí)表,導(dǎo)致嚴(yán)重的性能開(kāi)銷。

  • 4、枚舉類型(ENUM),把不重復(fù)的數(shù)據(jù)存儲(chǔ)為一個(gè)預(yù)定義的集合。
    有時(shí)可以使用ENUM代替常用的字符串類型。
    ENUM存儲(chǔ)非常緊湊,會(huì)把列表值壓縮到一個(gè)或兩個(gè)字節(jié)。
    ENUM在內(nèi)部存儲(chǔ)時(shí),其實(shí)存的是整數(shù)。
    盡量避免使用數(shù)字作為ENUM枚舉的常量,因?yàn)槿菀谆靵y。
    排序是按照內(nèi)部存儲(chǔ)的整數(shù)

  • 5、日期和時(shí)間類型,盡量使用timestamp,空間效率高于datetime,
    用整數(shù)保存時(shí)間戳通常不方便處理。
    如果需要存儲(chǔ)微妙,可以使用bigint存儲(chǔ)。
    看到這里,這道真題是不是就比較容易回答了。

引擎

MySQL存儲(chǔ)引擎MyISAM與InnoDB區(qū)別

存儲(chǔ)引擎Storage engine:MySQL中的數(shù)據(jù)、索引以及其他對(duì)象是如何存儲(chǔ)的,是一套文件系統(tǒng)的實(shí)現(xiàn)。

常用的存儲(chǔ)引擎有以下:

  • Innodb引擎:Innodb引擎提供了對(duì)數(shù)據(jù)庫(kù)ACID事務(wù)的支持。并且還提供了行級(jí)鎖和外鍵的約束。它的設(shè)計(jì)的目標(biāo)就是處理大數(shù)據(jù)容量的數(shù)據(jù)庫(kù)系統(tǒng)。
  • MyIASM引擎(原本Mysql的默認(rèn)引擎):不提供事務(wù)的支持,也不支持行級(jí)鎖和外鍵。
  • MEMORY引擎:所有的數(shù)據(jù)都在內(nèi)存中,數(shù)據(jù)的處理速度快,但是安全性不高。

MyISAM與InnoDB區(qū)別

MyISAMInnodb
存儲(chǔ)結(jié)構(gòu)每張表被存放在三個(gè)文件:frm-表格定義、MYD(MYData)-數(shù)據(jù)文件、MYI(MYIndex)-索引文件所有的表都保存在同一個(gè)數(shù)據(jù)文件中(也可能是多個(gè)文件,或者是獨(dú)立的表空間文件),InnoDB表的大小只受限于操作系統(tǒng)文件的大小,一般為2GB
存儲(chǔ)空間MyISAM可被壓縮,存儲(chǔ)空間較小InnoDB的表需要更多的內(nèi)存和存儲(chǔ),它會(huì)在主內(nèi)存中建立其專用的緩沖池用于高速緩沖數(shù)據(jù)和索引
可移植性、備份及恢復(fù)由于MyISAM的數(shù)據(jù)是以文件的形式存儲(chǔ),所以在跨平臺(tái)的數(shù)據(jù)轉(zhuǎn)移中會(huì)很方便。在備份和恢復(fù)時(shí)可單獨(dú)針對(duì)某個(gè)表進(jìn)行操作免費(fèi)的方案可以是拷貝數(shù)據(jù)文件、備份 binlog,或者用 mysqldump,在數(shù)據(jù)量達(dá)到幾十G的時(shí)候就相對(duì)痛苦了
文件格式數(shù)據(jù)和索引是分別存儲(chǔ)的,數(shù)據(jù).MYD,索引.MYI數(shù)據(jù)和索引是集中存儲(chǔ)的,.ibd
記錄存儲(chǔ)順序按記錄插入順序保存按主鍵大小有序插入
外鍵不支持支持
事務(wù)不支持支持
鎖支持(鎖是避免資源爭(zhēng)用的一個(gè)機(jī)制,MySQL鎖對(duì)用戶幾乎是透明的)表級(jí)鎖定行級(jí)鎖定、表級(jí)鎖定,鎖定力度小并發(fā)能力高
SELECTMyISAM更優(yōu)
INSERT、UPDATE、DELETEInnoDB更優(yōu)
select count(*)myisam更快,因?yàn)閙yisam內(nèi)部維護(hù)了一個(gè)計(jì)數(shù)器,可以直接調(diào)取。
索引的實(shí)現(xiàn)方式B+樹索引,myisam 是堆表B+樹索引,Innodb 是索引組織表
哈希索引不支持支持
全文索引支持不支持

MyISAM索引與InnoDB索引的區(qū)別?

  • InnoDB索引是聚簇索引,MyISAM索引是非聚簇索引。
  • InnoDB的主鍵索引的葉子節(jié)點(diǎn)存儲(chǔ)著行數(shù)據(jù),因此主鍵索引非常高效。
  • MyISAM索引的葉子節(jié)點(diǎn)存儲(chǔ)的是行數(shù)據(jù)地址,需要再尋址一次才能得到數(shù)據(jù)。
  • InnoDB非主鍵索引的葉子節(jié)點(diǎn)存儲(chǔ)的是主鍵和其他帶索引的列數(shù)據(jù),因此查詢時(shí)做到覆蓋索引會(huì)非常高效。

InnoDB引擎的4大特性

  • 插入緩沖(insert buffer)

  • 二次寫(double write)

  • 自適應(yīng)哈希索引(ahi)

  • 預(yù)讀(read ahead)

存儲(chǔ)引擎選擇

如果沒(méi)有特別的需求,使用默認(rèn)的Innodb即可。

MyISAM:以讀寫插入為主的應(yīng)用程序,比如博客系統(tǒng)、新聞門戶網(wǎng)站。

Innodb:更新(刪除)操作頻率也高,或者要保證數(shù)據(jù)的完整性;并發(fā)量高,支持事務(wù)和外鍵。比如OA自動(dòng)化辦公系統(tǒng)。

索引

什么是索引?

索引是一種特殊的文件(InnoDB數(shù)據(jù)表上的索引是表空間的一個(gè)組成部分),它們包含著對(duì)數(shù)據(jù)表里所有記錄的引用指針。

索引是一種數(shù)據(jù)結(jié)構(gòu)。數(shù)據(jù)庫(kù)索引,是數(shù)據(jù)庫(kù)管理系統(tǒng)中一個(gè)排序的數(shù)據(jù)結(jié)構(gòu),以協(xié)助快速查詢、更新數(shù)據(jù)庫(kù)表中數(shù)據(jù)。索引的實(shí)現(xiàn)通常使用B樹及其變種B+樹。

更通俗的說(shuō),索引就相當(dāng)于目錄。為了方便查找書中的內(nèi)容,通過(guò)對(duì)內(nèi)容建立索引形成目錄。索引是一個(gè)文件,它是要占據(jù)物理空間的。

索引有哪些優(yōu)缺點(diǎn)?

索引的優(yōu)點(diǎn)

  • 可以大大加快數(shù)據(jù)的檢索速度,這也是創(chuàng)建索引的最主要的原因。
  • 通過(guò)使用索引,可以在查詢的過(guò)程中,使用優(yōu)化隱藏器,提高系統(tǒng)的性能。

索引的缺點(diǎn)

  • 時(shí)間方面:創(chuàng)建索引和維護(hù)索引要耗費(fèi)時(shí)間,具體地,當(dāng)對(duì)表中的數(shù)據(jù)進(jìn)行增加、刪除和修改的時(shí)候,索引也要?jiǎng)討B(tài)的維護(hù),會(huì)降低增/改/刪的執(zhí)行效率;
  • 空間方面:索引需要占物理空間。

索引使用場(chǎng)景(重點(diǎn))

where

上圖中,根據(jù)id查詢記錄,因?yàn)閕d字段僅建立了主鍵索引,因此此SQL執(zhí)行可選的索引只有主鍵索引,如果有多個(gè),最終會(huì)選一個(gè)較優(yōu)的作為檢索的依據(jù)。

-- 增加一個(gè)沒(méi)有建立索引的字段 alter table innodb1 add sex char(1); -- 按sex檢索時(shí)可選的索引為null EXPLAIN SELECT * from innodb1 where sex='男';

可以嘗試在一個(gè)字段未建立索引時(shí),根據(jù)該字段查詢的效率,然后對(duì)該字段建立索引(alter table 表名 add index(字段名)),同樣的SQL執(zhí)行的效率,你會(huì)發(fā)現(xiàn)查詢效率會(huì)有明顯的提升(數(shù)據(jù)量越大越明顯)。

order by

當(dāng)我們使用order by將查詢結(jié)果按照某個(gè)字段排序時(shí),如果該字段沒(méi)有建立索引,那么執(zhí)行計(jì)劃會(huì)將查詢出的所有數(shù)據(jù)使用外部排序(將數(shù)據(jù)從硬盤分批讀取到內(nèi)存使用內(nèi)部排序,最后合并排序結(jié)果),這個(gè)操作是很影響性能的,因?yàn)樾枰獙⒉樵兩婕暗降乃袛?shù)據(jù)從磁盤中讀到內(nèi)存(如果單條數(shù)據(jù)過(guò)大或者數(shù)據(jù)量過(guò)多都會(huì)降低效率),更無(wú)論讀到內(nèi)存之后的排序了。

但是如果我們對(duì)該字段建立索引alter table 表名 add index(字段名),那么由于索引本身是有序的,因此直接按照索引的順序和映射關(guān)系逐條取出數(shù)據(jù)即可。而且如果分頁(yè)的,那么只用取出索引表某個(gè)范圍內(nèi)的索引對(duì)應(yīng)的數(shù)據(jù),而不用像上述那取出所有數(shù)據(jù)進(jìn)行排序再返回某個(gè)范圍內(nèi)的數(shù)據(jù)。(從磁盤取數(shù)據(jù)是最影響性能的)

join

對(duì)join語(yǔ)句匹配關(guān)系(on)涉及的字段建立索引能夠提高效率

索引覆蓋

如果要查詢的字段都建立過(guò)索引,那么引擎會(huì)直接在索引表中查詢而不會(huì)訪問(wèn)原始數(shù)據(jù)(否則只要有一個(gè)字段沒(méi)有建立索引就會(huì)做全表掃描),這叫索引覆蓋。因此我們需要盡可能的在select后只寫必要的查詢字段,以增加索引覆蓋的幾率。

這里值得注意的是不要想著為每個(gè)字段建立索引,因?yàn)閮?yōu)先使用索引的優(yōu)勢(shì)就在于其體積小。

索引有哪幾種類型?

主鍵索引: 數(shù)據(jù)列不允許重復(fù),不允許為NULL,一個(gè)表只能有一個(gè)主鍵。

唯一索引: 數(shù)據(jù)列不允許重復(fù),允許為NULL值,一個(gè)表允許多個(gè)列創(chuàng)建唯一索引。

  • 可以通過(guò) ALTER TABLE table_name ADD UNIQUE (column); 創(chuàng)建唯一索引

  • 可以通過(guò) ALTER TABLE table_name ADD UNIQUE (column1,column2); 創(chuàng)建唯一組合索引

普通索引: 基本的索引類型,沒(méi)有唯一性的限制,允許為NULL值。

  • 可以通過(guò)ALTER TABLE table_name ADD INDEX index_name (column);創(chuàng)建普通索引

  • 可以通過(guò)ALTER TABLE table_name ADD INDEX index_name(column1, column2, column3);創(chuàng)建組合索引

全文索引: 是目前搜索引擎使用的一種關(guān)鍵技術(shù)。

  • 可以通過(guò)ALTER TABLE table_name ADD FULLTEXT (column);創(chuàng)建全文索引

索引的數(shù)據(jù)結(jié)構(gòu)(b樹,hash)

索引的數(shù)據(jù)結(jié)構(gòu)和具體存儲(chǔ)引擎的實(shí)現(xiàn)有關(guān),在MySQL中使用較多的索引有Hash索引B+樹索引等,而我們經(jīng)常使用的InnoDB存儲(chǔ)引擎的默認(rèn)索引實(shí)現(xiàn)為:B+樹索引。對(duì)于哈希索引來(lái)說(shuō),底層的數(shù)據(jù)結(jié)構(gòu)就是哈希表,因此在絕大多數(shù)需求為單條記錄查詢的時(shí)候,可以選擇哈希索引,查詢性能最快;其余大部分場(chǎng)景,建議選擇BTree索引。

1)B樹索引

mysql通過(guò)存儲(chǔ)引擎取數(shù)據(jù),基本上90%的人用的就是InnoDB了,按照實(shí)現(xiàn)方式分,InnoDB的索引類型目前只有兩種:BTREE(B樹)索引和HASH索引。B樹索引是Mysql數(shù)據(jù)庫(kù)中使用最頻繁的索引類型,基本所有存儲(chǔ)引擎都支持BTree索引。通常我們說(shuō)的索引不出意外指的就是(B樹)索引(實(shí)際是用B+樹實(shí)現(xiàn)的,因?yàn)樵诓榭幢硭饕龝r(shí),mysql一律打印BTREE,所以簡(jiǎn)稱為B樹索引)

查詢方式:

主鍵索引區(qū):PI(關(guān)聯(lián)保存的時(shí)數(shù)據(jù)的地址)按主鍵查詢,

普通索引區(qū):si(關(guān)聯(lián)的id的地址,然后再到達(dá)上面的地址)。所以按主鍵查詢,速度最快

B+tree性質(zhì):

1.)n棵子tree的節(jié)點(diǎn)包含n個(gè)關(guān)鍵字,不用來(lái)保存數(shù)據(jù)而是保存數(shù)據(jù)的索引。

2.)所有的葉子結(jié)點(diǎn)中包含了全部關(guān)鍵字的信息,及指向含這些關(guān)鍵字記錄的指針,且葉子結(jié)點(diǎn)本身依關(guān)鍵字的大小自小而大順序鏈接。

3.)所有的非終端結(jié)點(diǎn)可以看成是索引部分,結(jié)點(diǎn)中僅含其子樹中的最大(或最小)關(guān)鍵字。

4.)B+ 樹中,數(shù)據(jù)對(duì)象的插入和刪除僅在葉節(jié)點(diǎn)上進(jìn)行。

5.)B+樹有2個(gè)頭指針,一個(gè)是樹的根節(jié)點(diǎn),一個(gè)是最小關(guān)鍵碼的葉節(jié)點(diǎn)。

2)哈希索引

簡(jiǎn)要說(shuō)下,類似于數(shù)據(jù)結(jié)構(gòu)中簡(jiǎn)單實(shí)現(xiàn)的HASH表(散列表)一樣,當(dāng)我們?cè)趍ysql中用哈希索引時(shí),主要就是通過(guò)Hash算法(常見(jiàn)的Hash算法有直接定址法、平方取中法、折疊法、除數(shù)取余法、隨機(jī)數(shù)法),將數(shù)據(jù)庫(kù)字段數(shù)據(jù)轉(zhuǎn)換成定長(zhǎng)的Hash值,與這條數(shù)據(jù)的行指針一并存入Hash表的對(duì)應(yīng)位置;如果發(fā)生Hash碰撞(兩個(gè)不同關(guān)鍵字的Hash值相同),則在對(duì)應(yīng)Hash鍵下以鏈表形式存儲(chǔ)。當(dāng)然這只是簡(jiǎn)略模擬圖。

索引的基本原理

索引用來(lái)快速地尋找那些具有特定值的記錄。如果沒(méi)有索引,一般來(lái)說(shuō)執(zhí)行查詢時(shí)遍歷整張表。

索引的原理很簡(jiǎn)單,就是把無(wú)序的數(shù)據(jù)變成有序的查詢

  • 把創(chuàng)建了索引的列的內(nèi)容進(jìn)行排序

  • 對(duì)排序結(jié)果生成倒排表

  • 在倒排表內(nèi)容上拼上數(shù)據(jù)地址鏈

  • 在查詢的時(shí)候,先拿到倒排表內(nèi)容,再取出數(shù)據(jù)地址鏈,從而拿到具體數(shù)據(jù)

  • 索引算法有哪些?

    索引算法有 BTree算法和Hash算法

    BTree算法

    BTree是最常用的mysql數(shù)據(jù)庫(kù)索引算法,也是mysql默認(rèn)的算法。因?yàn)樗粌H可以被用在=,>,>=,<,<=和between這些比較操作符上,而且還可以用于like操作符,只要它的查詢條件是一個(gè)不以通配符開(kāi)頭的常量, 例如:

    -- 只要它的查詢條件是一個(gè)不以通配符開(kāi)頭的常量 select * from user where name like 'jack%'; -- 如果一通配符開(kāi)頭,或者沒(méi)有使用常量,則不會(huì)使用索引,例如: select * from user where name like '%jack';

    Hash算法

    Hash Hash索引只能用于對(duì)等比較,例如=,<=>(相當(dāng)于=)操作符。由于是一次定位數(shù)據(jù),不像BTree索引需要從根節(jié)點(diǎn)到枝節(jié)點(diǎn),最后才能訪問(wèn)到頁(yè)節(jié)點(diǎn)這樣多次IO訪問(wèn),所以檢索效率遠(yuǎn)高于BTree索引。

    索引設(shè)計(jì)的原則?

  • 適合索引的列是出現(xiàn)在where子句中的列,或者連接子句中指定的列
  • 基數(shù)較小的類,索引效果較差,沒(méi)有必要在此列建立索引
  • 使用短索引,如果對(duì)長(zhǎng)字符串列進(jìn)行索引,應(yīng)該指定一個(gè)前綴長(zhǎng)度,這樣能夠節(jié)省大量索引空間
  • 不要過(guò)度索引。索引需要額外的磁盤空間,并降低寫操作的性能。在修改表內(nèi)容的時(shí)候,索引會(huì)進(jìn)行更新甚至重構(gòu),索引列越多,這個(gè)時(shí)間就會(huì)越長(zhǎng)。所以只保持需要的索引有利于查詢即可。
  • 創(chuàng)建索引的原則(重中之重)

    索引雖好,但也不是無(wú)限制的使用,最好符合一下幾個(gè)原則

    1) 最左前綴匹配原則,組合索引非常重要的原則,mysql會(huì)一直向右匹配直到遇到范圍查詢(>、<、between、like)就停止匹配,比如a = 1 and b = 2 and c > 3 and d = 4 如果建立(a,b,c,d)順序的索引,d是用不到索引的,如果建立(a,b,d,c)的索引則都可以用到,a,b,d的順序可以任意調(diào)整。

    2)較頻繁作為查詢條件的字段才去創(chuàng)建索引

    3)更新頻繁字段不適合創(chuàng)建索引

    4)若是不能有效區(qū)分?jǐn)?shù)據(jù)的列不適合做索引列(如性別,男女未知,最多也就三種,區(qū)分度實(shí)在太低)

    5)盡量的擴(kuò)展索引,不要新建索引。比如表中已經(jīng)有a的索引,現(xiàn)在要加(a,b)的索引,那么只需要修改原來(lái)的索引即可。

    6)定義有外鍵的數(shù)據(jù)列一定要建立索引。

    7)對(duì)于那些查詢中很少涉及的列,重復(fù)值比較多的列不要建立索引。

    8)對(duì)于定義為text、image和bit的數(shù)據(jù)類型的列不要建立索引。

    創(chuàng)建索引的三種方式,刪除索引

    第一種方式:在執(zhí)行CREATE TABLE時(shí)創(chuàng)建索引

    CREATE TABLE user_index2 (id INT auto_increment PRIMARY KEY,first_name VARCHAR (16),last_name VARCHAR (16),id_card VARCHAR (18),information text,KEY name (first_name, last_name),FULLTEXT KEY (information),UNIQUE KEY (id_card) );

    第二種方式:使用ALTER TABLE命令去增加索引

    ALTER TABLE table_name ADD INDEX index_name (column_list);

    ALTER TABLE用來(lái)創(chuàng)建普通索引、UNIQUE索引或PRIMARY KEY索引。

    其中table_name是要增加索引的表名,column_list指出對(duì)哪些列進(jìn)行索引,多列時(shí)各列之間用逗號(hào)分隔。

    索引名index_name可自己命名,缺省時(shí),MySQL將根據(jù)第一個(gè)索引列賦一個(gè)名稱。另外,ALTER TABLE允許在單個(gè)語(yǔ)句中更改多個(gè)表,因此可以在同時(shí)創(chuàng)建多個(gè)索引。

    第三種方式:使用CREATE INDEX命令創(chuàng)建

    CREATE INDEX index_name ON table_name (column_list);

    CREATE INDEX可對(duì)表增加普通索引或UNIQUE索引。(但是,不能創(chuàng)建PRIMARY KEY索引)

    刪除索引

    根據(jù)索引名刪除普通索引、唯一索引、全文索引:alter table 表名 drop KEY 索引名

    alter table user_index drop KEY name; alter table user_index drop KEY id_card; alter table user_index drop KEY information;

    刪除主鍵索引:alter table 表名 drop primary key(因?yàn)橹麈I只有一個(gè))。這里值得注意的是,如果主鍵自增長(zhǎng),那么不能直接執(zhí)行此操作(自增長(zhǎng)依賴于主鍵索引):

    需要取消自增長(zhǎng)再行刪除:

    alter table user_index -- 重新定義字段 MODIFY id int, drop PRIMARY KEY

    但通常不會(huì)刪除主鍵,因?yàn)樵O(shè)計(jì)主鍵一定與業(yè)務(wù)邏輯無(wú)關(guān)。

    創(chuàng)建索引時(shí)需要注意什么?

    • 非空字段:應(yīng)該指定列為NOT NULL,除非你想存儲(chǔ)NULL。在mysql中,含有空值的列很難進(jìn)行查詢優(yōu)化,因?yàn)樗鼈兪沟盟饕⑺饕慕y(tǒng)計(jì)信息以及比較運(yùn)算更加復(fù)雜。你應(yīng)該用0、一個(gè)特殊的值或者一個(gè)空串代替空值;
    • 取值離散大的字段:(變量各個(gè)取值之間的差異程度)的列放到聯(lián)合索引的前面,可以通過(guò)count()函數(shù)查看字段的差異值,返回值越大說(shuō)明字段的唯一值越多字段的離散程度高;
    • 索引字段越小越好:數(shù)據(jù)庫(kù)的數(shù)據(jù)存儲(chǔ)以頁(yè)為單位一頁(yè)存儲(chǔ)的數(shù)據(jù)越多一次IO操作獲取的數(shù)據(jù)越大效率越高。

    使用索引查詢一定能提高查詢的性能嗎?為什么

    通常,通過(guò)索引查詢數(shù)據(jù)比全表掃描要快。但是我們也必須注意到它的代價(jià)。

    • 索引需要空間來(lái)存儲(chǔ),也需要定期維護(hù), 每當(dāng)有記錄在表中增減或索引列被修改時(shí),索引本身也會(huì)被修改。 這意味著每條記錄的INSERT,DELETE,UPDATE將為此多付出4,5 次的磁盤I/O。 因?yàn)樗饕枰~外的存儲(chǔ)空間和處理,那些不必要的索引反而會(huì)使查詢反應(yīng)時(shí)間變慢。使用索引查詢不一定能提高查詢性能,索引范圍查詢(INDEX RANGE SCAN)適用于兩種情況:
    • 基于一個(gè)范圍的檢索,一般查詢返回結(jié)果集小于表中記錄數(shù)的30%
    • 基于非唯一性索引的檢索

    百萬(wàn)級(jí)別或以上的數(shù)據(jù)如何刪除

    關(guān)于索引:由于索引需要額外的維護(hù)成本,因?yàn)樗饕募菃为?dú)存在的文件,所以當(dāng)我們對(duì)數(shù)據(jù)的增加,修改,刪除,都會(huì)產(chǎn)生額外的對(duì)索引文件的操作,這些操作需要消耗額外的IO,會(huì)降低增/改/刪的執(zhí)行效率。所以,在我們刪除數(shù)據(jù)庫(kù)百萬(wàn)級(jí)別數(shù)據(jù)的時(shí)候,查詢MySQL官方手冊(cè)得知?jiǎng)h除數(shù)據(jù)的速度和創(chuàng)建的索引數(shù)量是成正比的。

  • 所以我們想要?jiǎng)h除百萬(wàn)數(shù)據(jù)的時(shí)候可以先刪除索引(此時(shí)大概耗時(shí)三分多鐘)
  • 然后刪除其中無(wú)用數(shù)據(jù)(此過(guò)程需要不到兩分鐘)
  • 刪除完成后重新創(chuàng)建索引(此時(shí)數(shù)據(jù)較少了)創(chuàng)建索引也非常快,約十分鐘左右。
  • 與之前的直接刪除絕對(duì)是要快速很多,更別說(shuō)萬(wàn)一刪除中斷,一切刪除會(huì)回滾。那更是坑了。
  • 前綴索引

    語(yǔ)法:index(field(10)),使用字段值的前10個(gè)字符建立索引,默認(rèn)是使用字段的全部?jī)?nèi)容建立索引。

    前提:前綴的標(biāo)識(shí)度高。比如密碼就適合建立前綴索引,因?yàn)槊艽a幾乎各不相同。

    實(shí)操的難度:在于前綴截取的長(zhǎng)度。

    我們可以利用select count(*)/count(distinct left(password,prefixLen));,通過(guò)從調(diào)整prefixLen的值(從1自增)查看不同前綴長(zhǎng)度的一個(gè)平均匹配度,接近1時(shí)就可以了(表示一個(gè)密碼的前prefixLen個(gè)字符幾乎能確定唯一一條記錄)

    什么是最左前綴原則?什么是最左匹配原則

    • 顧名思義,就是最左優(yōu)先,在創(chuàng)建多列索引時(shí),要根據(jù)業(yè)務(wù)需求,where子句中使用最頻繁的一列放在最左邊。
    • 最左前綴匹配原則,非常重要的原則,mysql會(huì)一直向右匹配直到遇到范圍查詢(>、<、between、like)就停止匹配,比如a = 1 and b = 2 and c > 3 and d = 4 如果建立(a,b,c,d)順序的索引,d是用不到索引的,如果建立(a,b,d,c)的索引則都可以用到,a,b,d的順序可以任意調(diào)整。
    • =和in可以亂序,比如a = 1 and b = 2 and c = 3 建立(a,b,c)索引可以任意順序,mysql的查詢優(yōu)化器會(huì)幫你優(yōu)化成索引可以識(shí)別的形式

    B樹和B+樹的區(qū)別

    • 在B樹中,你可以將鍵和值存放在內(nèi)部節(jié)點(diǎn)和葉子節(jié)點(diǎn);但在B+樹中,內(nèi)部節(jié)點(diǎn)都是鍵,沒(méi)有值,葉子節(jié)點(diǎn)同時(shí)存放鍵和值。

    • B+樹的葉子節(jié)點(diǎn)有一條鏈相連,而B樹的葉子節(jié)點(diǎn)各自獨(dú)立。

    使用B樹的好處

    B樹可以在內(nèi)部節(jié)點(diǎn)同時(shí)存儲(chǔ)鍵和值,因此,把頻繁訪問(wèn)的數(shù)據(jù)放在靠近根節(jié)點(diǎn)的地方將會(huì)大大提高熱點(diǎn)數(shù)據(jù)的查詢效率。這種特性使得B樹在特定數(shù)據(jù)重復(fù)多次查詢的場(chǎng)景中更加高效。

    使用B+樹的好處

    由于B+樹的內(nèi)部節(jié)點(diǎn)只存放鍵,不存放值,因此,一次讀取,可以在內(nèi)存頁(yè)中獲取更多的鍵,有利于更快地縮小查找范圍。 B+樹的葉節(jié)點(diǎn)由一條鏈相連,因此,當(dāng)需要進(jìn)行一次全數(shù)據(jù)遍歷的時(shí)候,B+樹只需要使用O(logN)時(shí)間找到最小的一個(gè)節(jié)點(diǎn),然后通過(guò)鏈進(jìn)行O(N)的順序遍歷即可。而B樹則需要對(duì)樹的每一層進(jìn)行遍歷,這會(huì)需要更多的內(nèi)存置換次數(shù),因此也就需要花費(fèi)更多的時(shí)間

    Hash索引和B+樹所有有什么區(qū)別或者說(shuō)優(yōu)劣呢?

    首先要知道Hash索引和B+樹索引的底層實(shí)現(xiàn)原理:

    hash索引底層就是hash表,進(jìn)行查找時(shí),調(diào)用一次hash函數(shù)就可以獲取到相應(yīng)的鍵值,之后進(jìn)行回表查詢獲得實(shí)際數(shù)據(jù)。B+樹底層實(shí)現(xiàn)是多路平衡查找樹。對(duì)于每一次的查詢都是從根節(jié)點(diǎn)出發(fā),查找到葉子節(jié)點(diǎn)方可以獲得所查鍵值,然后根據(jù)查詢判斷是否需要回表查詢數(shù)據(jù)。

    那么可以看出他們有以下的不同:

    • hash索引進(jìn)行等值查詢更快(一般情況下),但是卻無(wú)法進(jìn)行范圍查詢。

    因?yàn)樵趆ash索引中經(jīng)過(guò)hash函數(shù)建立索引之后,索引的順序與原順序無(wú)法保持一致,不能支持范圍查詢。而B+樹的的所有節(jié)點(diǎn)皆遵循(左節(jié)點(diǎn)小于父節(jié)點(diǎn),右節(jié)點(diǎn)大于父節(jié)點(diǎn),多叉樹也類似),天然支持范圍。

    • hash索引不支持使用索引進(jìn)行排序,原理同上。
    • hash索引不支持模糊查詢以及多列索引的最左前綴匹配。原理也是因?yàn)閔ash函數(shù)的不可預(yù)測(cè)。AAAA和AAAAB的索引沒(méi)有相關(guān)性。
    • hash索引任何時(shí)候都避免不了回表查詢數(shù)據(jù),而B+樹在符合某些條件(聚簇索引,覆蓋索引等)的時(shí)候可以只通過(guò)索引完成查詢。
    • hash索引雖然在等值查詢上較快,但是不穩(wěn)定。性能不可預(yù)測(cè),當(dāng)某個(gè)鍵值存在大量重復(fù)的時(shí)候,發(fā)生hash碰撞,此時(shí)效率可能極差。而B+樹的查詢效率比較穩(wěn)定,對(duì)于所有的查詢都是從根節(jié)點(diǎn)到葉子節(jié)點(diǎn),且樹的高度較低。

    因此,在大多數(shù)情況下,直接選擇B+樹索引可以獲得穩(wěn)定且較好的查詢速度。而不需要使用hash索引。

    數(shù)據(jù)庫(kù)為什么使用B+樹而不是B樹

    • B樹只適合隨機(jī)檢索,而B+樹同時(shí)支持隨機(jī)檢索和順序檢索;
    • B+樹空間利用率更高,可減少I/O次數(shù),磁盤讀寫代價(jià)更低。一般來(lái)說(shuō),索引本身也很大,不可能全部存儲(chǔ)在內(nèi)存中,因此索引往往以索引文件的形式存儲(chǔ)的磁盤上。這樣的話,索引查找過(guò)程中就要產(chǎn)生磁盤I/O消耗。B+樹的內(nèi)部結(jié)點(diǎn)并沒(méi)有指向關(guān)鍵字具體信息的指針,只是作為索引使用,其內(nèi)部結(jié)點(diǎn)比B樹小,盤塊能容納的結(jié)點(diǎn)中關(guān)鍵字?jǐn)?shù)量更多,一次性讀入內(nèi)存中可以查找的關(guān)鍵字也就越多,相對(duì)的,IO讀寫次數(shù)也就降低了。而IO讀寫次數(shù)是影響索引檢索效率的最大因素;
    • B+樹的查詢效率更加穩(wěn)定。B樹搜索有可能會(huì)在非葉子結(jié)點(diǎn)結(jié)束,越靠近根節(jié)點(diǎn)的記錄查找時(shí)間越短,只要找到關(guān)鍵字即可確定記錄的存在,其性能等價(jià)于在關(guān)鍵字全集內(nèi)做一次二分查找。而在B+樹中,順序檢索比較明顯,隨機(jī)檢索時(shí),任何關(guān)鍵字的查找都必須走一條從根節(jié)點(diǎn)到葉節(jié)點(diǎn)的路,所有關(guān)鍵字的查找路徑長(zhǎng)度相同,導(dǎo)致每一個(gè)關(guān)鍵字的查詢效率相當(dāng)。
    • B-樹在提高了磁盤IO性能的同時(shí)并沒(méi)有解決元素遍歷的效率低下的問(wèn)題。B+樹的葉子節(jié)點(diǎn)使用指針順序連接在一起,只要遍歷葉子節(jié)點(diǎn)就可以實(shí)現(xiàn)整棵樹的遍歷。而且在數(shù)據(jù)庫(kù)中基于范圍的查詢是非常頻繁的,而B樹不支持這樣的操作。
    • 增刪文件(節(jié)點(diǎn))時(shí),效率更高。因?yàn)锽+樹的葉子節(jié)點(diǎn)包含所有關(guān)鍵字,并以有序的鏈表結(jié)構(gòu)存儲(chǔ),這樣可很好提高增刪效率。

    B+樹在滿足聚簇索引和覆蓋索引的時(shí)候不需要回表查詢數(shù)據(jù),

    在B+樹的索引中,葉子節(jié)點(diǎn)可能存儲(chǔ)了當(dāng)前的key值,也可能存儲(chǔ)了當(dāng)前的key值以及整行的數(shù)據(jù),這就是聚簇索引和非聚簇索引。 在InnoDB中,只有主鍵索引是聚簇索引,如果沒(méi)有主鍵,則挑選一個(gè)唯一鍵建立聚簇索引。如果沒(méi)有唯一鍵,則隱式的生成一個(gè)鍵來(lái)建立聚簇索引。

    當(dāng)查詢使用聚簇索引時(shí),在對(duì)應(yīng)的葉子節(jié)點(diǎn),可以獲取到整行數(shù)據(jù),因此不用再次進(jìn)行回表查詢。

    什么是聚簇索引?何時(shí)使用聚簇索引與非聚簇索引

    • 聚簇索引:將數(shù)據(jù)存儲(chǔ)與索引放到了一塊,找到索引也就找到了數(shù)據(jù)
    • 非聚簇索引:將數(shù)據(jù)存儲(chǔ)于索引分開(kāi)結(jié)構(gòu),索引結(jié)構(gòu)的葉子節(jié)點(diǎn)指向了數(shù)據(jù)的對(duì)應(yīng)行,myisam通過(guò)key_buffer把索引先緩存到內(nèi)存中,當(dāng)需要訪問(wèn)數(shù)據(jù)時(shí)(通過(guò)索引訪問(wèn)數(shù)據(jù)),在內(nèi)存中直接搜索索引,然后通過(guò)索引找到磁盤相應(yīng)數(shù)據(jù),這也就是為什么索引不在key buffer命中時(shí),速度慢的原因

    澄清一個(gè)概念:innodb中,在聚簇索引之上創(chuàng)建的索引稱之為輔助索引,輔助索引訪問(wèn)數(shù)據(jù)總是需要二次查找,非聚簇索引都是輔助索引,像復(fù)合索引、前綴索引、唯一索引,輔助索引葉子節(jié)點(diǎn)存儲(chǔ)的不再是行的物理位置,而是主鍵值

    何時(shí)使用聚簇索引與非聚簇索引

    非聚簇索引一定會(huì)回表查詢嗎?

    不一定,這涉及到查詢語(yǔ)句所要求的字段是否全部命中了索引,如果全部命中了索引,那么就不必再進(jìn)行回表查詢。

    舉個(gè)簡(jiǎn)單的例子,假設(shè)我們?cè)趩T工表的年齡上建立了索引,那么當(dāng)進(jìn)行select age from employee where age < 20的查詢時(shí),在索引的葉子節(jié)點(diǎn)上,已經(jīng)包含了age信息,不會(huì)再次進(jìn)行回表查詢。

    聯(lián)合索引是什么?為什么需要注意聯(lián)合索引中的順序?

    MySQL可以使用多個(gè)字段同時(shí)建立一個(gè)索引,叫做聯(lián)合索引。在聯(lián)合索引中,如果想要命中索引,需要按照建立索引時(shí)的字段順序挨個(gè)使用,否則無(wú)法命中索引。

    具體原因?yàn)?

    MySQL使用索引時(shí)需要索引有序,假設(shè)現(xiàn)在建立了"name,age,school"的聯(lián)合索引,那么索引的排序?yàn)? 先按照name排序,如果name相同,則按照age排序,如果age的值也相等,則按照school進(jìn)行排序。

    當(dāng)進(jìn)行查詢時(shí),此時(shí)索引僅僅按照name嚴(yán)格有序,因此必須首先使用name字段進(jìn)行等值查詢,之后對(duì)于匹配到的列而言,其按照age字段嚴(yán)格有序,此時(shí)可以使用age字段用做索引查找,以此類推。因此在建立聯(lián)合索引的時(shí)候應(yīng)該注意索引列的順序,一般情況下,將查詢需求頻繁或者字段選擇性高的列放在前面。此外可以根據(jù)特例的查詢或者表結(jié)構(gòu)進(jìn)行單獨(dú)的調(diào)整。

    事務(wù)

    什么是數(shù)據(jù)庫(kù)事務(wù)?

    事務(wù)是一個(gè)不可分割的數(shù)據(jù)庫(kù)操作序列,也是數(shù)據(jù)庫(kù)并發(fā)控制的基本單位,其執(zhí)行的結(jié)果必須使數(shù)據(jù)庫(kù)從一種一致性狀態(tài)變到另一種一致性狀態(tài)。事務(wù)是邏輯上的一組操作,要么都執(zhí)行,要么都不執(zhí)行。

    事務(wù)最經(jīng)典也經(jīng)常被拿出來(lái)說(shuō)例子就是轉(zhuǎn)賬了。

    假如小明要給小紅轉(zhuǎn)賬1000元,這個(gè)轉(zhuǎn)賬會(huì)涉及到兩個(gè)關(guān)鍵操作就是:將小明的余額減少1000元,將小紅的余額增加1000元。萬(wàn)一在這兩個(gè)操作之間突然出現(xiàn)錯(cuò)誤比如銀行系統(tǒng)崩潰,導(dǎo)致小明余額減少而小紅的余額沒(méi)有增加,這樣就不對(duì)了。事務(wù)就是保證這兩個(gè)關(guān)鍵操作要么都成功,要么都要失敗。

    事物的四大特性(ACID)介紹一下?

    關(guān)系性數(shù)據(jù)庫(kù)需要遵循ACID規(guī)則,具體內(nèi)容如下:

  • 原子性: 事務(wù)是最小的執(zhí)行單位,不允許分割。事務(wù)的原子性確保動(dòng)作要么全部完成,要么完全不起作用;
  • 一致性: 執(zhí)行事務(wù)前后,數(shù)據(jù)保持一致,多個(gè)事務(wù)對(duì)同一個(gè)數(shù)據(jù)讀取的結(jié)果是相同的;
  • 隔離性: 并發(fā)訪問(wèn)數(shù)據(jù)庫(kù)時(shí),一個(gè)用戶的事務(wù)不被其他事務(wù)所干擾,各并發(fā)事務(wù)之間數(shù)據(jù)庫(kù)是獨(dú)立的;
  • 持久性: 一個(gè)事務(wù)被提交之后。它對(duì)數(shù)據(jù)庫(kù)中數(shù)據(jù)的改變是持久的,即使數(shù)據(jù)庫(kù)發(fā)生故障也不應(yīng)該對(duì)其有任何影響。
  • 什么是臟讀?幻讀?不可重復(fù)讀?

    • 臟讀(Drity Read):某個(gè)事務(wù)已更新一份數(shù)據(jù),另一個(gè)事務(wù)在此時(shí)讀取了同一份數(shù)據(jù),由于某些原因,前一個(gè)RollBack了操作,則后一個(gè)事務(wù)所讀取的數(shù)據(jù)就會(huì)是不正確的。
    • 不可重復(fù)讀(Non-repeatable read):在一個(gè)事務(wù)的兩次查詢之中數(shù)據(jù)不一致,這可能是兩次查詢過(guò)程中間插入了一個(gè)事務(wù)更新的原有的數(shù)據(jù)。
    • 幻讀(Phantom Read):在一個(gè)事務(wù)的兩次查詢中數(shù)據(jù)筆數(shù)不一致,例如有一個(gè)事務(wù)查詢了幾列(Row)數(shù)據(jù),而另一個(gè)事務(wù)卻在此時(shí)插入了新的幾列數(shù)據(jù),先前的事務(wù)在接下來(lái)的查詢中,就會(huì)發(fā)現(xiàn)有幾列數(shù)據(jù)是它先前所沒(méi)有的。

    什么是事務(wù)的隔離級(jí)別?MySQL的默認(rèn)隔離級(jí)別是什么?

    為了達(dá)到事務(wù)的四大特性,數(shù)據(jù)庫(kù)定義了4種不同的事務(wù)隔離級(jí)別,由低到高依次為Read uncommitted、Read committed、Repeatable read、Serializable,這四個(gè)級(jí)別可以逐個(gè)解決臟讀、不可重復(fù)讀、幻讀這幾類問(wèn)題。

    隔離級(jí)別臟讀不可重復(fù)讀幻影讀
    READ-UNCOMMITTED
    READ-COMMITTED×
    REPEATABLE-READ××
    SERIALIZABLE×××

    SQL 標(biāo)準(zhǔn)定義了四個(gè)隔離級(jí)別:

    • READ-UNCOMMITTED(讀取未提交): 最低的隔離級(jí)別,允許讀取尚未提交的數(shù)據(jù)變更,可能會(huì)導(dǎo)致臟讀、幻讀或不可重復(fù)讀
    • READ-COMMITTED(讀取已提交): 允許讀取并發(fā)事務(wù)已經(jīng)提交的數(shù)據(jù),可以阻止臟讀,但是幻讀或不可重復(fù)讀仍有可能發(fā)生
    • REPEATABLE-READ(可重復(fù)讀): 對(duì)同一字段的多次讀取結(jié)果都是一致的,除非數(shù)據(jù)是被本身事務(wù)自己所修改,可以阻止臟讀和不可重復(fù)讀,但幻讀仍有可能發(fā)生
    • SERIALIZABLE(可串行化): 最高的隔離級(jí)別,完全服從ACID的隔離級(jí)別。所有的事務(wù)依次逐個(gè)執(zhí)行,這樣事務(wù)之間就完全不可能產(chǎn)生干擾,也就是說(shuō),該級(jí)別可以防止臟讀、不可重復(fù)讀以及幻讀

    這里需要注意的是:Mysql 默認(rèn)采用的 REPEATABLE_READ隔離級(jí)別 Oracle 默認(rèn)采用的 READ_COMMITTED隔離級(jí)別

    事務(wù)隔離機(jī)制的實(shí)現(xiàn)基于鎖機(jī)制和并發(fā)調(diào)度。其中并發(fā)調(diào)度使用的是MVVC(多版本并發(fā)控制),通過(guò)保存修改的舊版本信息來(lái)支持并發(fā)一致性讀和回滾等特性。

    因?yàn)楦綦x級(jí)別越低,事務(wù)請(qǐng)求的鎖越少,所以大部分?jǐn)?shù)據(jù)庫(kù)系統(tǒng)的隔離級(jí)別都是READ-COMMITTED(讀取提交內(nèi)容):,但是你要知道的是InnoDB 存儲(chǔ)引擎默認(rèn)使用 **REPEATABLE-READ(可重讀)**并不會(huì)有任何性能損失。

    InnoDB 存儲(chǔ)引擎在 分布式事務(wù) 的情況下一般會(huì)用到**SERIALIZABLE(可串行化)**隔離級(jí)別。

    對(duì)MySQL的鎖了解嗎

    當(dāng)數(shù)據(jù)庫(kù)有并發(fā)事務(wù)的時(shí)候,可能會(huì)產(chǎn)生數(shù)據(jù)的不一致,這時(shí)候需要一些機(jī)制來(lái)保證訪問(wèn)的次序,鎖機(jī)制就是這樣的一個(gè)機(jī)制。

    就像酒店的房間,如果大家隨意進(jìn)出,就會(huì)出現(xiàn)多人搶奪同一個(gè)房間的情況,而在房間上裝上鎖,申請(qǐng)到鑰匙的人才可以入住并且將房間鎖起來(lái),其他人只有等他使用完畢才可以再次使用。

    隔離級(jí)別與鎖的關(guān)系

    在Read Uncommitted級(jí)別下,讀取數(shù)據(jù)不需要加共享鎖,這樣就不會(huì)跟被修改的數(shù)據(jù)上的排他鎖沖突

    在Read Committed級(jí)別下,讀操作需要加共享鎖,但是在語(yǔ)句執(zhí)行完以后釋放共享鎖;

    在Repeatable Read級(jí)別下,讀操作需要加共享鎖,但是在事務(wù)提交之前并不釋放共享鎖,也就是必須等待事務(wù)執(zhí)行完畢以后才釋放共享鎖。

    SERIALIZABLE 是限制性最強(qiáng)的隔離級(jí)別,因?yàn)樵摷?jí)別鎖定整個(gè)范圍的鍵,并一直持有鎖,直到事務(wù)完成。

    按照鎖的粒度分?jǐn)?shù)據(jù)庫(kù)鎖有哪些?鎖機(jī)制與InnoDB鎖算法

    在關(guān)系型數(shù)據(jù)庫(kù)中,可以按照鎖的粒度把數(shù)據(jù)庫(kù)鎖分為行級(jí)鎖(INNODB引擎)、表級(jí)鎖(MYISAM引擎)和頁(yè)級(jí)鎖(BDB引擎 )。

    MyISAM和InnoDB存儲(chǔ)引擎使用的鎖:

    • MyISAM采用表級(jí)鎖(table-level locking)。
    • InnoDB支持行級(jí)鎖(row-level locking)和表級(jí)鎖,默認(rèn)為行級(jí)鎖

    行級(jí)鎖,表級(jí)鎖和頁(yè)級(jí)鎖對(duì)比

    行級(jí)鎖 行級(jí)鎖是Mysql中鎖定粒度最細(xì)的一種鎖,表示只針對(duì)當(dāng)前操作的行進(jìn)行加鎖。行級(jí)鎖能大大減少數(shù)據(jù)庫(kù)操作的沖突。其加鎖粒度最小,但加鎖的開(kāi)銷也最大。行級(jí)鎖分為共享鎖 和 排他鎖。

    特點(diǎn):開(kāi)銷大,加鎖慢;會(huì)出現(xiàn)死鎖;鎖定粒度最小,發(fā)生鎖沖突的概率最低,并發(fā)度也最高。

    表級(jí)鎖 表級(jí)鎖是MySQL中鎖定粒度最大的一種鎖,表示對(duì)當(dāng)前操作的整張表加鎖,它實(shí)現(xiàn)簡(jiǎn)單,資源消耗較少,被大部分MySQL引擎支持。最常使用的MYISAM與INNODB都支持表級(jí)鎖定。表級(jí)鎖定分為表共享讀鎖(共享鎖)與表獨(dú)占寫鎖(排他鎖)。

    特點(diǎn):開(kāi)銷小,加鎖快;不會(huì)出現(xiàn)死鎖;鎖定粒度大,發(fā)出鎖沖突的概率最高,并發(fā)度最低。

    頁(yè)級(jí)鎖 頁(yè)級(jí)鎖是MySQL中鎖定粒度介于行級(jí)鎖和表級(jí)鎖中間的一種鎖。表級(jí)鎖速度快,但沖突多,行級(jí)沖突少,但速度慢。所以取了折衷的頁(yè)級(jí),一次鎖定相鄰的一組記錄。

    特點(diǎn):開(kāi)銷和加鎖時(shí)間界于表鎖和行鎖之間;會(huì)出現(xiàn)死鎖;鎖定粒度界于表鎖和行鎖之間,并發(fā)度一般

    從鎖的類別上分MySQL都有哪些鎖呢?像上面那樣子進(jìn)行鎖定豈不是有點(diǎn)阻礙并發(fā)效率了

    從鎖的類別上來(lái)講,有共享鎖和排他鎖。

    共享鎖: 又叫做讀鎖。 當(dāng)用戶要進(jìn)行數(shù)據(jù)的讀取時(shí),對(duì)數(shù)據(jù)加上共享鎖。共享鎖可以同時(shí)加上多個(gè)。

    排他鎖: 又叫做寫鎖。 當(dāng)用戶要進(jìn)行數(shù)據(jù)的寫入時(shí),對(duì)數(shù)據(jù)加上排他鎖。排他鎖只可以加一個(gè),他和其他的排他鎖,共享鎖都相斥。

    用上面的例子來(lái)說(shuō)就是用戶的行為有兩種,一種是來(lái)看房,多個(gè)用戶一起看房是可以接受的。 一種是真正的入住一晚,在這期間,無(wú)論是想入住的還是想看房的都不可以。

    鎖的粒度取決于具體的存儲(chǔ)引擎,InnoDB實(shí)現(xiàn)了行級(jí)鎖,頁(yè)級(jí)鎖,表級(jí)鎖。

    他們的加鎖開(kāi)銷從大到小,并發(fā)能力也是從大到小。

    MySQL中InnoDB引擎的行鎖是怎么實(shí)現(xiàn)的?

    答:InnoDB是基于索引來(lái)完成行鎖

    例: select * from tab_with_index where id = 1 for update;

    for update 可以根據(jù)條件來(lái)完成行鎖鎖定,并且 id 是有索引鍵的列,如果 id 不是索引鍵那么InnoDB將完成表鎖,并發(fā)將無(wú)從談起

    InnoDB存儲(chǔ)引擎的鎖的算法有三種

    • Record lock:單個(gè)行記錄上的鎖
    • Gap lock:間隙鎖,鎖定一個(gè)范圍,不包括記錄本身
    • Next-key lock:record+gap 鎖定一個(gè)范圍,包含記錄本身

    相關(guān)知識(shí)點(diǎn):

  • innodb對(duì)于行的查詢使用next-key lock
  • Next-locking keying為了解決Phantom Problem幻讀問(wèn)題
  • 當(dāng)查詢的索引含有唯一屬性時(shí),將next-key lock降級(jí)為record key
  • Gap鎖設(shè)計(jì)的目的是為了阻止多個(gè)事務(wù)將記錄插入到同一范圍內(nèi),而這會(huì)導(dǎo)致幻讀問(wèn)題的產(chǎn)生
  • 有兩種方式顯式關(guān)閉gap鎖:(除了外鍵約束和唯一性檢查外,其余情況僅使用record lock) A. 將事務(wù)隔離級(jí)別設(shè)置為RC B. 將參數(shù)innodb_locks_unsafe_for_binlog設(shè)置為1
  • 什么是死鎖?怎么解決?

    死鎖是指兩個(gè)或多個(gè)事務(wù)在同一資源上相互占用,并請(qǐng)求鎖定對(duì)方的資源,從而導(dǎo)致惡性循環(huán)的現(xiàn)象。

    常見(jiàn)的解決死鎖的方法

    1、如果不同程序會(huì)并發(fā)存取多個(gè)表,盡量約定以相同的順序訪問(wèn)表,可以大大降低死鎖機(jī)會(huì)。

    2、在同一個(gè)事務(wù)中,盡可能做到一次鎖定所需要的所有資源,減少死鎖產(chǎn)生概率;

    3、對(duì)于非常容易產(chǎn)生死鎖的業(yè)務(wù)部分,可以嘗試使用升級(jí)鎖定顆粒度,通過(guò)表級(jí)鎖定來(lái)減少死鎖產(chǎn)生的概率;

    如果業(yè)務(wù)處理不好可以用分布式事務(wù)鎖或者使用樂(lè)觀鎖

    數(shù)據(jù)庫(kù)的樂(lè)觀鎖和悲觀鎖是什么?怎么實(shí)現(xiàn)的?

    數(shù)據(jù)庫(kù)管理系統(tǒng)(DBMS)中的并發(fā)控制的任務(wù)是確保在多個(gè)事務(wù)同時(shí)存取數(shù)據(jù)庫(kù)中同一數(shù)據(jù)時(shí)不破壞事務(wù)的隔離性和統(tǒng)一性以及數(shù)據(jù)庫(kù)的統(tǒng)一性。樂(lè)觀并發(fā)控制(樂(lè)觀鎖)和悲觀并發(fā)控制(悲觀鎖)是并發(fā)控制主要采用的技術(shù)手段。

    悲觀鎖:假定會(huì)發(fā)生并發(fā)沖突,屏蔽一切可能違反數(shù)據(jù)完整性的操作。在查詢完數(shù)據(jù)的時(shí)候就把事務(wù)鎖起來(lái),直到提交事務(wù)。實(shí)現(xiàn)方式:使用數(shù)據(jù)庫(kù)中的鎖機(jī)制

    樂(lè)觀鎖:假設(shè)不會(huì)發(fā)生并發(fā)沖突,只在提交操作時(shí)檢查是否違反數(shù)據(jù)完整性。在修改數(shù)據(jù)的時(shí)候把事務(wù)鎖起來(lái),通過(guò)version的方式來(lái)進(jìn)行鎖定。實(shí)現(xiàn)方式:樂(lè)一般會(huì)使用版本號(hào)機(jī)制或CAS算法實(shí)現(xiàn)。

    兩種鎖的使用場(chǎng)景

    從上面對(duì)兩種鎖的介紹,我們知道兩種鎖各有優(yōu)缺點(diǎn),不可認(rèn)為一種好于另一種,像樂(lè)觀鎖適用于寫比較少的情況下(多讀場(chǎng)景),即沖突真的很少發(fā)生的時(shí)候,這樣可以省去了鎖的開(kāi)銷,加大了系統(tǒng)的整個(gè)吞吐量。

    但如果是多寫的情況,一般會(huì)經(jīng)常產(chǎn)生沖突,這就會(huì)導(dǎo)致上層應(yīng)用會(huì)不斷的進(jìn)行retry,這樣反倒是降低了性能,所以一般多寫的場(chǎng)景下用悲觀鎖就比較合適。

    視圖

    為什么要使用視圖?什么是視圖?

    為了提高復(fù)雜SQL語(yǔ)句的復(fù)用性和表操作的安全性,MySQL數(shù)據(jù)庫(kù)管理系統(tǒng)提供了視圖特性。所謂視圖,本質(zhì)上是一種虛擬表,在物理上是不存在的,其內(nèi)容與真實(shí)的表相似,包含一系列帶有名稱的列和行數(shù)據(jù)。但是,視圖并不在數(shù)據(jù)庫(kù)中以儲(chǔ)存的數(shù)據(jù)值形式存在。行和列數(shù)據(jù)來(lái)自定義視圖的查詢所引用基本表,并且在具體引用視圖時(shí)動(dòng)態(tài)生成。

    視圖使開(kāi)發(fā)者只關(guān)心感興趣的某些特定數(shù)據(jù)和所負(fù)責(zé)的特定任務(wù),只能看到視圖中所定義的數(shù)據(jù),而不是視圖所引用表中的數(shù)據(jù),從而提高了數(shù)據(jù)庫(kù)中數(shù)據(jù)的安全性。

    視圖有哪些特點(diǎn)?

    視圖的特點(diǎn)如下:

    • 視圖的列可以來(lái)自不同的表,是表的抽象和在邏輯意義上建立的新關(guān)系。

    • 視圖是由基本表(實(shí)表)產(chǎn)生的表(虛表)。

    • 視圖的建立和刪除不影響基本表。

    • 對(duì)視圖內(nèi)容的更新(添加,刪除和修改)直接影響基本表。

    • 當(dāng)視圖來(lái)自多個(gè)基本表時(shí),不允許添加和刪除數(shù)據(jù)。

    視圖的操作包括創(chuàng)建視圖,查看視圖,刪除視圖和修改視圖。

    視圖的使用場(chǎng)景有哪些?

    視圖根本用途:簡(jiǎn)化sql查詢,提高開(kāi)發(fā)效率。如果說(shuō)還有另外一個(gè)用途那就是兼容老的表結(jié)構(gòu)。

    下面是視圖的常見(jiàn)使用場(chǎng)景:

    • 重用SQL語(yǔ)句;

    • 簡(jiǎn)化復(fù)雜的SQL操作。在編寫查詢后,可以方便的重用它而不必知道它的基本查詢細(xì)節(jié);

    • 使用表的組成部分而不是整個(gè)表;

    • 保護(hù)數(shù)據(jù)。可以給用戶授予表的特定部分的訪問(wèn)權(quán)限而不是整個(gè)表的訪問(wèn)權(quán)限;

    • 更改數(shù)據(jù)格式和表示。視圖可返回與底層表的表示和格式不同的數(shù)據(jù)。

    視圖的優(yōu)點(diǎn)

  • 查詢簡(jiǎn)單化。視圖能簡(jiǎn)化用戶的操作
  • 數(shù)據(jù)安全性。視圖使用戶能以多種角度看待同一數(shù)據(jù),能夠?qū)C(jī)密數(shù)據(jù)提供安全保護(hù)
  • 邏輯數(shù)據(jù)獨(dú)立性。視圖對(duì)重構(gòu)數(shù)據(jù)庫(kù)提供了一定程度的邏輯獨(dú)立性
  • 視圖的缺點(diǎn)

  • 性能。數(shù)據(jù)庫(kù)必須把視圖的查詢轉(zhuǎn)化成對(duì)基本表的查詢,如果這個(gè)視圖是由一個(gè)復(fù)雜的多表查詢所定義,那么,即使是視圖的一個(gè)簡(jiǎn)單查詢,數(shù)據(jù)庫(kù)也把它變成一個(gè)復(fù)雜的結(jié)合體,需要花費(fèi)一定的時(shí)間。

  • 修改限制。當(dāng)用戶試圖修改視圖的某些行時(shí),數(shù)據(jù)庫(kù)必須把它轉(zhuǎn)化為對(duì)基本表的某些行的修改。事實(shí)上,當(dāng)從視圖中插入或者刪除時(shí),情況也是這樣。對(duì)于簡(jiǎn)單視圖來(lái)說(shuō),這是很方便的,但是,對(duì)于比較復(fù)雜的視圖,可能是不可修改的

    這些視圖有如下特征:1.有UNIQUE等集合操作符的視圖。2.有GROUP BY子句的視圖。3.有諸如AVG\SUM\MAX等聚合函數(shù)的視圖。 4.使用DISTINCT關(guān)鍵字的視圖。5.連接表的視圖(其中有些例外)

  • 什么是游標(biāo)?

    游標(biāo)是系統(tǒng)為用戶開(kāi)設(shè)的一個(gè)數(shù)據(jù)緩沖區(qū),存放SQL語(yǔ)句的執(zhí)行結(jié)果,每個(gè)游標(biāo)區(qū)都有一個(gè)名字。用戶可以通過(guò)游標(biāo)逐一獲取記錄并賦給主變量,交由主語(yǔ)言進(jìn)一步處理。

    存儲(chǔ)過(guò)程與函數(shù)

    什么是存儲(chǔ)過(guò)程?有哪些優(yōu)缺點(diǎn)?

    存儲(chǔ)過(guò)程是一個(gè)預(yù)編譯的SQL語(yǔ)句,優(yōu)點(diǎn)是允許模塊化的設(shè)計(jì),就是說(shuō)只需要?jiǎng)?chuàng)建一次,以后在該程序中就可以調(diào)用多次。如果某次操作需要執(zhí)行多次SQL,使用存儲(chǔ)過(guò)程比單純SQL語(yǔ)句執(zhí)行要快。

    優(yōu)點(diǎn)

    1)存儲(chǔ)過(guò)程是預(yù)編譯過(guò)的,執(zhí)行效率高。

    2)存儲(chǔ)過(guò)程的代碼直接存放于數(shù)據(jù)庫(kù)中,通過(guò)存儲(chǔ)過(guò)程名直接調(diào)用,減少網(wǎng)絡(luò)通訊。

    3)安全性高,執(zhí)行存儲(chǔ)過(guò)程需要有一定權(quán)限的用戶。

    4)存儲(chǔ)過(guò)程可以重復(fù)使用,減少數(shù)據(jù)庫(kù)開(kāi)發(fā)人員的工作量。

    缺點(diǎn)

    1)調(diào)試麻煩,但是用 PL/SQL Developer 調(diào)試很方便!彌補(bǔ)這個(gè)缺點(diǎn)。

    2)移植問(wèn)題,數(shù)據(jù)庫(kù)端代碼當(dāng)然是與數(shù)據(jù)庫(kù)相關(guān)的。但是如果是做工程型項(xiàng)目,基本不存在移植問(wèn)題。

    3)重新編譯問(wèn)題,因?yàn)楹蠖舜a是運(yùn)行前編譯的,如果帶有引用關(guān)系的對(duì)象發(fā)生改變時(shí),受影響的存儲(chǔ)過(guò)程、包將需要重新編譯(不過(guò)也可以設(shè)置成運(yùn)行時(shí)刻自動(dòng)編譯)。

    4)如果在一個(gè)程序系統(tǒng)中大量的使用存儲(chǔ)過(guò)程,到程序交付使用的時(shí)候隨著用戶需求的增加會(huì)導(dǎo)致數(shù)據(jù)結(jié)構(gòu)的變化,接著就是系統(tǒng)的相關(guān)問(wèn)題了,最后如果用戶想維護(hù)該系統(tǒng)可以說(shuō)是很難很難、而且代價(jià)是空前的,維護(hù)起來(lái)更麻煩。

    觸發(fā)器

    什么是觸發(fā)器?觸發(fā)器的使用場(chǎng)景有哪些?

    觸發(fā)器是用戶定義在關(guān)系表上的一類由事件驅(qū)動(dòng)的特殊的存儲(chǔ)過(guò)程。觸發(fā)器是指一段代碼,當(dāng)觸發(fā)某個(gè)事件時(shí),自動(dòng)執(zhí)行這些代碼。

    使用場(chǎng)景

    • 可以通過(guò)數(shù)據(jù)庫(kù)中的相關(guān)表實(shí)現(xiàn)級(jí)聯(lián)更改。
    • 實(shí)時(shí)監(jiān)控某張表中的某個(gè)字段的更改而需要做出相應(yīng)的處理。
    • 例如可以生成某些業(yè)務(wù)的編號(hào)。
    • 注意不要濫用,否則會(huì)造成數(shù)據(jù)庫(kù)及應(yīng)用程序的維護(hù)困難。
    • 大家需要牢記以上基礎(chǔ)知識(shí)點(diǎn),重點(diǎn)是理解數(shù)據(jù)類型CHAR和VARCHAR的差異,表存儲(chǔ)引擎InnoDB和MyISAM的區(qū)別。

    MySQL中都有哪些觸發(fā)器?

    在MySQL數(shù)據(jù)庫(kù)中有如下六種觸發(fā)器:

    • Before Insert
    • After Insert
    • Before Update
    • After Update
    • Before Delete
    • After Delete

    常用SQL語(yǔ)句

    SQL語(yǔ)句主要分為哪幾類

    數(shù)據(jù)定義語(yǔ)言DDL(Data Ddefinition Language)CREATE,DROP,ALTER

    主要為以上操作 即對(duì)邏輯結(jié)構(gòu)等有操作的,其中包括表結(jié)構(gòu),視圖和索引。

    數(shù)據(jù)查詢語(yǔ)言DQL(Data Query Language)SELECT

    這個(gè)較為好理解 即查詢操作,以select關(guān)鍵字。各種簡(jiǎn)單查詢,連接查詢等 都屬于DQL。

    數(shù)據(jù)操縱語(yǔ)言DML(Data Manipulation Language)INSERT,UPDATE,DELETE

    主要為以上操作 即對(duì)數(shù)據(jù)進(jìn)行操作的,對(duì)應(yīng)上面所說(shuō)的查詢操作 DQL與DML共同構(gòu)建了多數(shù)初級(jí)程序員常用的增刪改查操作。而查詢是較為特殊的一種 被劃分到DQL中。

    數(shù)據(jù)控制功能DCL(Data Control Language)GRANT,REVOKE,COMMIT,ROLLBACK

    主要為以上操作 即對(duì)數(shù)據(jù)庫(kù)安全性完整性等有操作的,可以簡(jiǎn)單的理解為權(quán)限控制等。

    超鍵、候選鍵、主鍵、外鍵分別是什么?

    • 超鍵:在關(guān)系中能唯一標(biāo)識(shí)元組的屬性集稱為關(guān)系模式的超鍵。一個(gè)屬性可以為作為一個(gè)超鍵,多個(gè)屬性組合在一起也可以作為一個(gè)超鍵。超鍵包含候選鍵和主鍵。
    • 候選鍵:是最小超鍵,即沒(méi)有冗余元素的超鍵。
    • 主鍵:數(shù)據(jù)庫(kù)表中對(duì)儲(chǔ)存數(shù)據(jù)對(duì)象予以唯一和完整標(biāo)識(shí)的數(shù)據(jù)列或?qū)傩缘慕M合。一個(gè)數(shù)據(jù)列只能有一個(gè)主鍵,且主鍵的取值不能缺失,即不能為空值(Null)。
    • 外鍵:在一個(gè)表中存在的另一個(gè)表的主鍵稱此表的外鍵。

    SQL 約束有哪幾種?

    SQL 約束有哪幾種?

    • NOT NULL: 用于控制字段的內(nèi)容一定不能為空(NULL)。
    • UNIQUE: 控件字段內(nèi)容不能重復(fù),一個(gè)表允許有多個(gè) Unique 約束。
    • PRIMARY KEY: 也是用于控件字段內(nèi)容不能重復(fù),但它在一個(gè)表只允許出現(xiàn)一個(gè)。
    • FOREIGN KEY: 用于預(yù)防破壞表之間連接的動(dòng)作,也能防止非法數(shù)據(jù)插入外鍵列,因?yàn)樗仨毷撬赶虻哪莻€(gè)表中的值之一。
    • CHECK: 用于控制字段的值范圍。

    六種關(guān)聯(lián)查詢

    • 交叉連接(CROSS JOIN)
    • 內(nèi)連接(INNER JOIN)
    • 外連接(LEFT JOIN/RIGHT JOIN)
    • 聯(lián)合查詢(UNION與UNION ALL)
    • 全連接(FULL JOIN)
    • 交叉連接(CROSS JOIN)
    SELECT * FROM A,B(,C)或者SELECT * FROM A CROSS JOIN B (CROSS JOIN C)#沒(méi)有任何關(guān)聯(lián)條件,結(jié)果是笛卡爾積,結(jié)果集會(huì)很大,沒(méi)有意義,很少使用內(nèi)連接(INNER JOIN)SELECT * FROM A,B WHERE A.id=B.id或者SELECT * FROM A INNER JOIN B ON A.id=B.id多表中同時(shí)符合某種條件的數(shù)據(jù)記錄的集合,INNER JOIN可以縮寫為JOIN

    內(nèi)連接分為三類

    • 等值連接:ON A.id=B.id
    • 不等值連接:ON A.id > B.id
    • 自連接:SELECT * FROM A T1 INNER JOIN A T2 ON T1.id=T2.pid

    外連接(LEFT JOIN/RIGHT JOIN)

    • 左外連接:LEFT OUTER JOIN, 以左表為主,先查詢出左表,按照ON后的關(guān)聯(lián)條件匹配右表,沒(méi)有匹配到的用NULL填充,可以簡(jiǎn)寫成LEFT JOIN
    • 右外連接:RIGHT OUTER JOIN, 以右表為主,先查詢出右表,按照ON后的關(guān)聯(lián)條件匹配左表,沒(méi)有匹配到的用NULL填充,可以簡(jiǎn)寫成RIGHT JOIN

    聯(lián)合查詢(UNION與UNION ALL)

    SELECT * FROM A UNION SELECT * FROM B UNION ...
    • 就是把多個(gè)結(jié)果集集中在一起,UNION前的結(jié)果為基準(zhǔn),需要注意的是聯(lián)合查詢的列數(shù)要相等,相同的記錄行會(huì)合并
    • 如果使用UNION ALL,不會(huì)合并重復(fù)的記錄行
    • 效率 UNION 高于 UNION ALL

    全連接(FULL JOIN)

    • MySQL不支持全連接
    • 可以使用LEFT JOIN 和UNION和RIGHT JOIN聯(lián)合使用
    SELECT * FROM A LEFT JOIN B ON A.id=B.id UNIONSELECT * FROM A RIGHT JOIN B ON A.id=B.id

    表連接面試題

    有2張表,1張R、1張S,R表有ABC三列,S表有CD兩列,表中各有三條記錄。

    R表

    ABC
    a1b1c1
    a2b2c2
    a3b3c3

    S表

    CD
    c1d1
    c2d2
    c4d3
  • 交叉連接(笛卡爾積):
  • select r.*,s.* from r,s

    ABCCD
    a1b1c1c1d1
    a2b2c2c1d1
    a3b3c3c1d1
    a1b1c1c2d2
    a2b2c2c2d2
    a3b3c3c2d2
    a1b1c1c4d3
    a2b2c2c4d3
    a3b3c3c4d3
  • 內(nèi)連接結(jié)果:

    select r.*,s.* from r inner join s on r.c=s.c

  • ABCCD
    a1b1c1c1d1
    a2b2c2c2d2
  • 左連接結(jié)果:

    select r.*,s.* from r left join s on r.c=s.c

  • ABCCD
    a1b1c1c1d1
    a2b2c2c2d2
    a3b3c3
  • 右連接結(jié)果:

    select r.*,s.* from r right join s on r.c=s.c

  • ABCCD
    a1b1c1c1d1
    a2b2c2c2d2
    c4d3
  • 全表連接的結(jié)果(MySql不支持,Oracle支持):

    select r.*,s.* from r full join s on r.c=s.c

  • ABCCD
    a1b1c1c1d1
    a2b2c2c2d2
    a3b3c3
    c4d3

    什么是子查詢

  • 條件:一條SQL語(yǔ)句的查詢結(jié)果做為另一條查詢語(yǔ)句的條件或查詢結(jié)果

  • 嵌套:多條SQL語(yǔ)句嵌套使用,內(nèi)部的SQL查詢語(yǔ)句稱為子查詢。

  • 子查詢的三種情況

  • 子查詢是單行單列的情況:結(jié)果集是一個(gè)值,父查詢使用:=、 <、 > 等運(yùn)算符
  • -- 查詢工資最高的員工是誰(shuí)? select * from employee where salary=(select max(salary) from employee);
  • 子查詢是多行單列的情況:結(jié)果集類似于一個(gè)數(shù)組,父查詢使用:in 運(yùn)算符
  • -- 查詢工資最高的員工是誰(shuí)? select * from employee where salary=(select max(salary) from employee);
  • 子查詢是多行多列的情況:結(jié)果集類似于一張?zhí)摂M表,不能用于where條件,用于select子句中做為子表
  • -- 1) 查詢出2011年以后入職的員工信息 -- 2) 查詢所有的部門信息,與上面的虛擬表中的信息比對(duì),找出所有部門ID相等的員工。 select * from dept d, (select * from employee where join_date > '2011-1-1') e where e.dept_id = d.id; -- 使用表連接: select d.*, e.* from dept d inner join employee e on d.id = e.dept_id where e.join_date > '2011-1-1'

    mysql中 in 和 exists 區(qū)別

    mysql中的in語(yǔ)句是把外表和內(nèi)表作hash 連接,而exists語(yǔ)句是對(duì)外表作loop循環(huán),每次loop循環(huán)再對(duì)內(nèi)表進(jìn)行查詢。一直大家都認(rèn)為exists比in語(yǔ)句的效率要高,這種說(shuō)法其實(shí)是不準(zhǔn)確的。這個(gè)是要區(qū)分環(huán)境的。

  • 如果查詢的兩個(gè)表大小相當(dāng),那么用in和exists差別不大。
  • 如果兩個(gè)表中一個(gè)較小,一個(gè)是大表,則子查詢表大的用exists,子查詢表小的用in。
  • not in 和not exists:如果查詢語(yǔ)句使用了not in,那么內(nèi)外表都進(jìn)行全表掃描,沒(méi)有用到索引;而not extsts的子查詢依然能用到表上的索引。所以無(wú)論那個(gè)表大,用not exists都比not in要快。
  • varchar與char的區(qū)別

    char的特點(diǎn)

    • 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的特點(diǎn)

    • 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

    總之,結(jié)合性能角度(char更快)和節(jié)省磁盤空間角度(varchar更小),具體情況還需具體來(lái)設(shè)計(jì)數(shù)據(jù)庫(kù)才是妥當(dāng)?shù)淖龇ā?/p>

    varchar(50)中50的涵義

    最多存放50個(gè)字符,varchar(50)和(200)存儲(chǔ)hello所占空間一樣,但后者在排序時(shí)會(huì)消耗更多內(nèi)存,因?yàn)閛rder by col采用fixed_length計(jì)算col長(zhǎng)度(memory引擎也一樣)。在早期 MySQL 版本中, 50 代表字節(jié)數(shù),現(xiàn)在代表字符數(shù)。

    int(20)中20的涵義

    是指顯示字符的長(zhǎng)度。20表示最大顯示寬度為20,但仍占4字節(jié)存儲(chǔ),存儲(chǔ)范圍不變;

    不影響內(nèi)部存儲(chǔ),只是影響帶 zerofill 定義的 int 時(shí),前面補(bǔ)多少個(gè) 0,易于報(bào)表展示

    mysql為什么這么設(shè)計(jì)

    對(duì)大多數(shù)應(yīng)用沒(méi)有意義,只是規(guī)定一些工具用來(lái)顯示字符的個(gè)數(shù);int(1)和int(20)存儲(chǔ)和計(jì)算均一樣;

    mysql中int(10)和char(10)以及varchar(10)的區(qū)別

    • int(10)的10表示顯示的數(shù)據(jù)的長(zhǎng)度,不是存儲(chǔ)數(shù)據(jù)的大小;chart(10)和varchar(10)的10表示存儲(chǔ)數(shù)據(jù)的大小,即表示存儲(chǔ)多少個(gè)字符。

      int(10) 10位的數(shù)據(jù)長(zhǎng)度 9999999999,占32個(gè)字節(jié),int型4位
      char(10) 10位固定字符串,不足補(bǔ)空格 最多10個(gè)字符
      varchar(10) 10位可變字符串,不足補(bǔ)空格 最多10個(gè)字符

    • char(10)表示存儲(chǔ)定長(zhǎng)的10個(gè)字符,不足10個(gè)就用空格補(bǔ)齊,占用更多的存儲(chǔ)空間

    • varchar(10)表示存儲(chǔ)10個(gè)變長(zhǎng)的字符,存儲(chǔ)多少個(gè)就是多少個(gè),空格也按一個(gè)字符存儲(chǔ),這一點(diǎn)是和char(10)的空格不同的,char(10)的空格表示占位不算一個(gè)字符

    FLOAT和DOUBLE的區(qū)別是什么?

    • FLOAT類型數(shù)據(jù)可以存儲(chǔ)至多8位十進(jìn)制數(shù),并在內(nèi)存中占4字節(jié)。
    • DOUBLE類型數(shù)據(jù)可以存儲(chǔ)至多18位十進(jìn)制數(shù),并在內(nèi)存中占8字節(jié)。

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

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

    DeleteTruncateDrop
    類型屬于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。

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

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

    SQL優(yōu)化

    如何定位及優(yōu)化SQL語(yǔ)句的性能問(wèn)題?創(chuàng)建的索引有沒(méi)有被使用到?或者說(shuō)怎么才可以知道這條語(yǔ)句運(yùn)行很慢的原因?

    對(duì)于低性能的SQL語(yǔ)句的定位,最重要也是最有效的方法就是使用執(zhí)行計(jì)劃,MySQL提供了explain命令來(lái)查看語(yǔ)句的執(zhí)行計(jì)劃。 我們知道,不管是哪種數(shù)據(jù)庫(kù),或者是哪種數(shù)據(jù)庫(kù)引擎,在對(duì)一條SQL語(yǔ)句進(jìn)行執(zhí)行的過(guò)程中都會(huì)做很多相關(guān)的優(yōu)化,對(duì)于查詢語(yǔ)句,最重要的優(yōu)化方式就是使用索引。 而執(zhí)行計(jì)劃,就是顯示數(shù)據(jù)庫(kù)引擎對(duì)于SQL語(yǔ)句的執(zhí)行的詳細(xì)情況,其中包含了是否使用索引,使用什么索引,使用的索引的相關(guān)信息等

    執(zhí)行計(jì)劃包含的信息 id 有一組數(shù)字組成。表示一個(gè)查詢中各個(gè)子查詢的執(zhí)行順序;

    • id相同執(zhí)行順序由上至下。
    • id不同,id值越大優(yōu)先級(jí)越高,越先被執(zhí)行。
    • id為null時(shí)表示一個(gè)結(jié)果集,不需要使用它查詢,常出現(xiàn)在包含union等查詢語(yǔ)句中。

    select_type 每個(gè)子查詢的查詢類型,一些常見(jiàn)的查詢類型。

    idselect_typedescription
    1SIMPLE不包含任何子查詢或union等查詢
    2PRIMARY包含子查詢最外層查詢就顯示為 PRIMARY
    3SUBQUERY在select或 where字句中包含的查詢
    4DERIVEDfrom字句中包含的查詢
    5UNION出現(xiàn)在union后的查詢語(yǔ)句中
    6UNION RESULT從UNION中獲取結(jié)果集,例如上文的第三個(gè)例子

    table 查詢的數(shù)據(jù)表,當(dāng)從衍生表中查數(shù)據(jù)時(shí)會(huì)顯示 x 表示對(duì)應(yīng)的執(zhí)行計(jì)劃id partitions 表分區(qū)、表創(chuàng)建的時(shí)候可以指定通過(guò)那個(gè)列進(jìn)行表分區(qū)。 舉個(gè)例子:

    create table tmp (id int unsigned not null AUTO_INCREMENT,name varchar(255),PRIMARY KEY (id) ) engine = innodb partition by key (id) partitions 5;

    type(非常重要,可以看到有沒(méi)有走索引) 訪問(wèn)類型

    • ALL 掃描全表數(shù)據(jù)
    • index 遍歷索引
    • range 索引范圍查找
    • index_subquery 在子查詢中使用 ref
    • unique_subquery 在子查詢中使用 eq_ref
    • ref_or_null 對(duì)Null進(jìn)行索引的優(yōu)化的 ref
    • fulltext 使用全文索引
    • ref 使用非唯一索引查找數(shù)據(jù)
    • eq_ref 在join查詢中使用PRIMARY KEYorUNIQUE NOT NULL索引關(guān)聯(lián)。

    possible_keys 可能使用的索引,注意不一定會(huì)使用。查詢涉及到的字段上若存在索引,則該索引將被列出來(lái)。當(dāng)該列為 NULL時(shí)就要考慮當(dāng)前的SQL是否需要優(yōu)化了。

    key 顯示MySQL在查詢中實(shí)際使用的索引,若沒(méi)有使用索引,顯示為NULL。

    TIPS:查詢中若使用了覆蓋索引(覆蓋索引:索引的數(shù)據(jù)覆蓋了需要查詢的所有數(shù)據(jù)),則該索引僅出現(xiàn)在key列表中

    key_length 索引長(zhǎng)度

    ref 表示上述表的連接匹配條件,即哪些列或常量被用于查找索引列上的值

    rows 返回估算的結(jié)果集數(shù)目,并不是一個(gè)準(zhǔn)確的值。

    extra 的信息非常豐富,常見(jiàn)的有:

  • Using index 使用覆蓋索引
  • Using where 使用了用where子句來(lái)過(guò)濾結(jié)果集
  • Using filesort 使用文件排序,使用非索引列進(jìn)行排序時(shí)出現(xiàn),非常消耗性能,盡量?jī)?yōu)化。
  • Using temporary 使用了臨時(shí)表 sql優(yōu)化的目標(biāo)可以參考阿里開(kāi)發(fā)手冊(cè)
  • 【推薦】SQL性能優(yōu)化的目標(biāo):至少要達(dá)到 range 級(jí)別,要求是ref級(jí)別,如果可以是consts最好。 說(shuō)明: 1) consts 單表中最多只有一個(gè)匹配行(主鍵或者唯一索引),在優(yōu)化階段即可讀取到數(shù)據(jù)。 2) ref 指的是使用普通的索引(normal index)。 3) range 對(duì)索引進(jìn)行范圍檢索。 反例:explain表的結(jié)果,type=index,索引物理文件全掃描,速度非常慢,這個(gè)index級(jí)別比較range還低,與全表掃描是小巫見(jiàn)大巫。

    SQL的生命周期?

  • 應(yīng)用服務(wù)器與數(shù)據(jù)庫(kù)服務(wù)器建立一個(gè)連接

  • 數(shù)據(jù)庫(kù)進(jìn)程拿到請(qǐng)求sql

  • 解析并生成執(zhí)行計(jì)劃,執(zhí)行

  • 讀取數(shù)據(jù)到內(nèi)存并進(jìn)行邏輯處理

  • 通過(guò)步驟一的連接,發(fā)送結(jié)果到客戶端

  • 關(guān)掉連接,釋放資源

  • 大表數(shù)據(jù)查詢,怎么優(yōu)化

  • 優(yōu)化shema、sql語(yǔ)句+索引;
  • 第二加緩存,memcached, redis;
  • 主從復(fù)制,讀寫分離;
  • 垂直拆分,根據(jù)你模塊的耦合度,將一個(gè)大的系統(tǒng)分為多個(gè)小的系統(tǒng),也就是分布式系統(tǒng);
  • 水平切分,針對(duì)數(shù)據(jù)量大的表,這一步最麻煩,最能考驗(yàn)技術(shù)水平,要選擇一個(gè)合理的sharding key, 為了有好的查詢效率,表結(jié)構(gòu)也要改動(dòng),做一定的冗余,應(yīng)用也要改,sql中盡量帶sharding key,將數(shù)據(jù)定位到限定的表上去查,而不是掃描全部的表;
  • 超大分頁(yè)怎么處理?

    超大的分頁(yè)一般從兩個(gè)方向上來(lái)解決.

    • 數(shù)據(jù)庫(kù)層面,這也是我們主要集中關(guān)注的(雖然收效沒(méi)那么大),類似于select * from table where age > 20 limit 1000000,10這種查詢其實(shí)也是有可以優(yōu)化的余地的. 這條語(yǔ)句需要load1000000數(shù)據(jù)然后基本上全部丟棄,只取10條當(dāng)然比較慢. 當(dāng)時(shí)我們可以修改為select * from table where id in (select id from table where age > 20 limit 1000000,10).這樣雖然也load了一百萬(wàn)的數(shù)據(jù),但是由于索引覆蓋,要查詢的所有字段都在索引中,所以速度會(huì)很快. 同時(shí)如果ID連續(xù)的好,我們還可以select * from table where id > 1000000 limit 10,效率也是不錯(cuò)的,優(yōu)化的可能性有許多種,但是核心思想都一樣,就是減少load的數(shù)據(jù).
    • 從需求的角度減少這種請(qǐng)求…主要是不做類似的需求(直接跳轉(zhuǎn)到幾百萬(wàn)頁(yè)之后的具體某一頁(yè).只允許逐頁(yè)查看或者按照給定的路線走,這樣可預(yù)測(cè),可緩存)以及防止ID泄漏且連續(xù)被人惡意攻擊.

    解決超大分頁(yè),其實(shí)主要是靠緩存,可預(yù)測(cè)性的提前查到內(nèi)容,緩存至redis等k-V數(shù)據(jù)庫(kù)中,直接返回即可.

    在阿里巴巴《Java開(kāi)發(fā)手冊(cè)》中,對(duì)超大分頁(yè)的解決辦法是類似于上面提到的第一種.

    【推薦】利用延遲關(guān)聯(lián)或者子查詢優(yōu)化超多分頁(yè)場(chǎng)景。 說(shuō)明:MySQL并不是跳過(guò)offset行,而是取offset+N行,然后返回放棄前offset行,返回N行,那當(dāng)offset特別大的時(shí)候,效率就非常的低下,要么控制返回的總頁(yè)數(shù),要么對(duì)超過(guò)特定閾值的頁(yè)數(shù)進(jìn)行SQL改寫。 正例:先快速定位需要獲取的id段,然后再關(guān)聯(lián): SELECT a.* FROM1 a, (select id from1 where 條件 LIMIT 100000,20 ) b where a.id=b.id

    mysql 分頁(yè)

    LIMIT 子句可以被用于強(qiáng)制 SELECT 語(yǔ)句返回指定的記錄數(shù)。LIMIT 接受一個(gè)或兩個(gè)數(shù)字參數(shù)。參數(shù)必須是一個(gè)整數(shù)常量。如果給定兩個(gè)參數(shù),第一個(gè)參數(shù)指定第一個(gè)返回記錄行的偏移量,第二個(gè)參數(shù)指定返回記錄行的最大數(shù)目。初始記錄行的偏移量是 0(而不是 1)

    mysql> SELECT * FROM table LIMIT 5,10; // 檢索記錄行 6-15

    為了檢索從某一個(gè)偏移量到記錄集的結(jié)束所有的記錄行,可以指定第二個(gè)參數(shù)為 -1:

    mysql> SELECT * FROM table LIMIT 95,-1; // 檢索記錄行 96-last.

    如果只給定一個(gè)參數(shù),它表示返回最大的記錄行數(shù)目:

    mysql> SELECT * FROM table LIMIT 5; //檢索前 5 個(gè)記錄行

    換句話說(shuō),LIMIT n 等價(jià)于 LIMIT 0,n。

    慢查詢?nèi)罩?/h3>

    用于記錄執(zhí)行時(shí)間超過(guò)某個(gè)臨界值的SQL日志,用于快速定位慢查詢,為我們的優(yōu)化做參考。

    開(kāi)啟慢查詢?nèi)罩?/p>

    配置項(xiàng):slow_query_log

    可以使用show variables like ‘slov_query_log’查看是否開(kāi)啟,如果狀態(tài)值為OFF,可以使用set GLOBAL slow_query_log = on來(lái)開(kāi)啟,它會(huì)在datadir下產(chǎn)生一個(gè)xxx-slow.log的文件。

    設(shè)置臨界時(shí)間

    配置項(xiàng):long_query_time

    查看:show VARIABLES like 'long_query_time',單位秒

    設(shè)置:set long_query_time=0.5

    實(shí)操時(shí)應(yīng)該從長(zhǎng)時(shí)間設(shè)置到短的時(shí)間,即將最慢的SQL優(yōu)化掉

    查看日志,一旦SQL超過(guò)了我們?cè)O(shè)置的臨界時(shí)間就會(huì)被記錄到xxx-slow.log中

    關(guān)心過(guò)業(yè)務(wù)系統(tǒng)里面的sql耗時(shí)嗎?統(tǒng)計(jì)過(guò)慢查詢嗎?對(duì)慢查詢都怎么優(yōu)化過(guò)?

    在業(yè)務(wù)系統(tǒng)中,除了使用主鍵進(jìn)行的查詢,其他的我都會(huì)在測(cè)試庫(kù)上測(cè)試其耗時(shí),慢查詢的統(tǒng)計(jì)主要由運(yùn)維在做,會(huì)定期將業(yè)務(wù)中的慢查詢反饋給我們。

    慢查詢的優(yōu)化首先要搞明白慢的原因是什么? 是查詢條件沒(méi)有命中索引?是load了不需要的數(shù)據(jù)列?還是數(shù)據(jù)量太大?

    所以優(yōu)化也是針對(duì)這三個(gè)方向來(lái)的,

    • 首先分析語(yǔ)句,看看是否load了額外的數(shù)據(jù),可能是查詢了多余的行并且拋棄掉了,可能是加載了許多結(jié)果中并不需要的列,對(duì)語(yǔ)句進(jìn)行分析以及重寫。
    • 分析語(yǔ)句的執(zhí)行計(jì)劃,然后獲得其使用索引的情況,之后修改語(yǔ)句或者修改索引,使得語(yǔ)句可以盡可能的命中索引。
    • 如果對(duì)語(yǔ)句的優(yōu)化已經(jīng)無(wú)法進(jìn)行,可以考慮表中的數(shù)據(jù)量是否太大,如果是的話可以進(jìn)行橫向或者縱向的分表。

    為什么要盡量設(shè)定一個(gè)主鍵?

    主鍵是數(shù)據(jù)庫(kù)確保數(shù)據(jù)行在整張表唯一性的保障,即使業(yè)務(wù)上本張表沒(méi)有主鍵,也建議添加一個(gè)自增長(zhǎng)的ID列作為主鍵。設(shè)定了主鍵之后,在后續(xù)的刪改查的時(shí)候可能更加快速以及確保操作數(shù)據(jù)范圍安全。

    主鍵使用自增ID還是UUID?

    推薦使用自增ID,不要使用UUID。

    因?yàn)樵贗nnoDB存儲(chǔ)引擎中,主鍵索引是作為聚簇索引存在的,也就是說(shuō),主鍵索引的B+樹葉子節(jié)點(diǎn)上存儲(chǔ)了主鍵索引以及全部的數(shù)據(jù)(按照順序),如果主鍵索引是自增ID,那么只需要不斷向后排列即可,如果是UUID,由于到來(lái)的ID與原來(lái)的大小不確定,會(huì)造成非常多的數(shù)據(jù)插入,數(shù)據(jù)移動(dòng),然后導(dǎo)致產(chǎn)生很多的內(nèi)存碎片,進(jìn)而造成插入性能的下降。

    總之,在數(shù)據(jù)量大一些的情況下,用自增主鍵性能會(huì)好一些。

    關(guān)于主鍵是聚簇索引,如果沒(méi)有主鍵,InnoDB會(huì)選擇一個(gè)唯一鍵來(lái)作為聚簇索引,如果沒(méi)有唯一鍵,會(huì)生成一個(gè)隱式的主鍵。

    字段為什么要求定義為not null?

    null值會(huì)占用更多的字節(jié),且會(huì)在程序中造成很多與預(yù)期不符的情況。

    如果要存儲(chǔ)用戶的密碼散列,應(yīng)該使用什么字段進(jìn)行存儲(chǔ)?

    密碼散列,鹽,用戶身份證號(hào)等固定長(zhǎng)度的字符串應(yīng)該使用char而不是varchar來(lái)存儲(chǔ),這樣可以節(jié)省空間且提高檢索效率。

    優(yōu)化查詢過(guò)程中的數(shù)據(jù)訪問(wèn)

    • 訪問(wèn)數(shù)據(jù)太多導(dǎo)致查詢性能下降
    • 確定應(yīng)用程序是否在檢索大量超過(guò)需要的數(shù)據(jù),可能是太多行或列
    • 確認(rèn)MySQL服務(wù)器是否在分析大量不必要的數(shù)據(jù)行
    • 避免犯如下SQL語(yǔ)句錯(cuò)誤
    • 查詢不需要的數(shù)據(jù)。解決辦法:使用limit解決
    • 多表關(guān)聯(lián)返回全部列。解決辦法:指定列名
    • 總是返回全部列。解決辦法:避免使用SELECT *
    • 重復(fù)查詢相同的數(shù)據(jù)。解決辦法:可以緩存數(shù)據(jù),下次直接讀取緩存
    • 是否在掃描額外的記錄。解決辦法:
    • 使用explain進(jìn)行分析,如果發(fā)現(xiàn)查詢需要掃描大量的數(shù)據(jù),但只返回少數(shù)的行,可以通過(guò)如下技巧去優(yōu)化:
    • 使用索引覆蓋掃描,把所有的列都放到索引中,這樣存儲(chǔ)引擎不需要回表獲取對(duì)應(yīng)行就可以返回結(jié)果。
    • 改變數(shù)據(jù)庫(kù)和表的結(jié)構(gòu),修改數(shù)據(jù)表范式
    • 重寫SQL語(yǔ)句,讓優(yōu)化器可以以更優(yōu)的方式執(zhí)行查詢。

    優(yōu)化長(zhǎng)難的查詢語(yǔ)句

    • 一個(gè)復(fù)雜查詢還是多個(gè)簡(jiǎn)單查詢
    • MySQL內(nèi)部每秒能掃描內(nèi)存中上百萬(wàn)行數(shù)據(jù),相比之下,響應(yīng)數(shù)據(jù)給客戶端就要慢得多
    • 使用盡可能小的查詢是好的,但是有時(shí)將一個(gè)大的查詢分解為多個(gè)小的查詢是很有必要的。
    • 切分查詢
    • 將一個(gè)大的查詢分為多個(gè)小的相同的查詢
    • 一次性刪除1000萬(wàn)的數(shù)據(jù)要比一次刪除1萬(wàn),暫停一會(huì)的方案更加損耗服務(wù)器開(kāi)銷。
    • 分解關(guān)聯(lián)查詢,讓緩存的效率更高。
    • 執(zhí)行單個(gè)查詢可以減少鎖的競(jìng)爭(zhēng)。
    • 在應(yīng)用層做關(guān)聯(lián)更容易對(duì)數(shù)據(jù)庫(kù)進(jìn)行拆分。
    • 查詢效率會(huì)有大幅提升。
    • 較少冗余記錄的查詢。

    優(yōu)化特定類型的查詢語(yǔ)句

    • count(*)會(huì)忽略所有的列,直接統(tǒng)計(jì)所有列數(shù),不要使用count(列名)
    • MyISAM中,沒(méi)有任何where條件的count(*)非常快。
    • 當(dāng)有where條件時(shí),MyISAM的count統(tǒng)計(jì)不一定比其它引擎快。
    • 可以使用explain查詢近似值,用近似值替代count(*)
    • 增加匯總表
    • 使用緩存

    優(yōu)化關(guān)聯(lián)查詢

    • 確定ON或者USING子句中是否有索引。
    • 確保GROUP BY和ORDER BY只有一個(gè)表中的列,這樣MySQL才有可能使用索引。

    優(yōu)化子查詢

    • 用關(guān)聯(lián)查詢替代
    • 優(yōu)化GROUP BY和DISTINCT
    • 這兩種查詢據(jù)可以使用索引來(lái)優(yōu)化,是最有效的優(yōu)化方法
    • 關(guān)聯(lián)查詢中,使用標(biāo)識(shí)列分組的效率更高
    • 如果不需要ORDER BY,進(jìn)行GROUP BY時(shí)加ORDER BY NULL,MySQL不會(huì)再進(jìn)行文件排序。
    • WITH ROLLUP超級(jí)聚合,可以挪到應(yīng)用程序處理

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

    • LIMIT偏移量大的時(shí)候,查詢效率較低
    • 可以記錄上次查詢的最大ID,下次查詢時(shí)直接根據(jù)該ID來(lái)查詢

    優(yōu)化UNION查詢

    • UNION ALL的效率高于UNION

    優(yōu)化WHERE子句

    解題方法

    對(duì)于此類考題,先說(shuō)明如何定位低效SQL語(yǔ)句,然后根據(jù)SQL語(yǔ)句可能低效的原因做排查,先從索引著手,如果索引沒(méi)有問(wèn)題,考慮以上幾個(gè)方面,數(shù)據(jù)訪問(wèn)的問(wèn)題,長(zhǎng)難查詢句的問(wèn)題還是一些特定類型優(yōu)化的問(wèn)題,逐一回答。

    SQL語(yǔ)句優(yōu)化的一些方法?

    • 1.對(duì)查詢進(jìn)行優(yōu)化,應(yīng)盡量避免全表掃描,首先應(yīng)考慮在 where 及 order by 涉及的列上建立索引。
    • 2.應(yīng)盡量避免在 where 子句中對(duì)字段進(jìn)行 null 值判斷,否則將導(dǎo)致引擎放棄使用索引而進(jìn)行全表掃描,如:
    select id from t where num is null -- 可以在num上設(shè)置默認(rèn)值0,確保表中num列沒(méi)有null值,然后這樣查詢: select id from t where num=
    • 3.應(yīng)盡量避免在 where 子句中使用!=或<>操作符,否則引擎將放棄使用索引而進(jìn)行全表掃描。
    • 4.應(yīng)盡量避免在 where 子句中使用or 來(lái)連接條件,否則將導(dǎo)致引擎放棄使用索引而進(jìn)行全表掃描,如:
    select id from t where num=10 or num=20 -- 可以這樣查詢: select id from t where num=10 union all select id from t where num=20
    • 5.in 和 not in 也要慎用,否則會(huì)導(dǎo)致全表掃描,如:
    select id from t where num in(1,2,3) -- 對(duì)于連續(xù)的數(shù)值,能用 between 就不要用 in 了: select id from t where num between 1 and 3
    • 6.下面的查詢也將導(dǎo)致全表掃描:select id from t where name like ‘%李%’若要提高效率,可以考慮全文檢索。
    • 7.如果在 where 子句中使用參數(shù),也會(huì)導(dǎo)致全表掃描。因?yàn)镾QL只有在運(yùn)行時(shí)才會(huì)解析局部變量,但優(yōu)化程序不能將訪問(wèn)計(jì)劃的選擇推遲到運(yùn)行時(shí);它必須在編譯時(shí)進(jìn)行選擇。然 而,如果在編譯時(shí)建立訪問(wèn)計(jì)劃,變量的值還是未知的,因而無(wú)法作為索引選擇的輸入項(xiàng)。如下面語(yǔ)句將進(jìn)行全表掃描:
    select id from t where num=@num -- 可以改為強(qiáng)制查詢使用索引: select id from t with(index(索引名)) where num=@num
    • 8.應(yīng)盡量避免在 where 子句中對(duì)字段進(jìn)行表達(dá)式操作,這將導(dǎo)致引擎放棄使用索引而進(jìn)行全表掃描。如:
    select id from t where num/2=100 -- 應(yīng)改為: select id from t where num=100*2
    • 9.應(yīng)盡量避免在where子句中對(duì)字段進(jìn)行函數(shù)操作,這將導(dǎo)致引擎放棄使用索引而進(jìn)行全表掃描。如:
    select id from t where substring(name,1,3)=’abc’ -- name以abc開(kāi)頭的id應(yīng)改為: select id from t where name like ‘a(chǎn)bc%
    • 10.不要在 where 子句中的“=”左邊進(jìn)行函數(shù)、算術(shù)運(yùn)算或其他表達(dá)式運(yùn)算,否則系統(tǒng)將可能無(wú)法正確使用索引。

    數(shù)據(jù)庫(kù)優(yōu)化

    為什么要優(yōu)化

    • 系統(tǒng)的吞吐量瓶頸往往出現(xiàn)在數(shù)據(jù)庫(kù)的訪問(wèn)速度上
    • 隨著應(yīng)用程序的運(yùn)行,數(shù)據(jù)庫(kù)的中的數(shù)據(jù)會(huì)越來(lái)越多,處理時(shí)間會(huì)相應(yīng)變慢
    • 數(shù)據(jù)是存放在磁盤上的,讀寫速度無(wú)法和內(nèi)存相比

    優(yōu)化原則:減少系統(tǒng)瓶頸,減少資源占用,增加系統(tǒng)的反應(yīng)速度。

    數(shù)據(jù)庫(kù)結(jié)構(gòu)優(yōu)化

    一個(gè)好的數(shù)據(jù)庫(kù)設(shè)計(jì)方案對(duì)于數(shù)據(jù)庫(kù)的性能往往會(huì)起到事半功倍的效果。

    需要考慮數(shù)據(jù)冗余、查詢和更新的速度、字段的數(shù)據(jù)類型是否合理等多方面的內(nèi)容。

    將字段很多的表分解成多個(gè)表

    對(duì)于字段較多的表,如果有些字段的使用頻率很低,可以將這些字段分離出來(lái)形成新表。

    因?yàn)楫?dāng)一個(gè)表的數(shù)據(jù)量很大時(shí),會(huì)由于使用頻率低的字段的存在而變慢。

    增加中間表

    對(duì)于需要經(jīng)常聯(lián)合查詢的表,可以建立中間表以提高查詢效率。

    通過(guò)建立中間表,將需要通過(guò)聯(lián)合查詢的數(shù)據(jù)插入到中間表中,然后將原來(lái)的聯(lián)合查詢改為對(duì)中間表的查詢。

    增加冗余字段

    設(shè)計(jì)數(shù)據(jù)表時(shí)應(yīng)盡量遵循范式理論的規(guī)約,盡可能的減少冗余字段,讓數(shù)據(jù)庫(kù)設(shè)計(jì)看起來(lái)精致、優(yōu)雅。但是,合理的加入冗余字段可以提高查詢速度。

    表的規(guī)范化程度越高,表和表之間的關(guān)系越多,需要連接查詢的情況也就越多,性能也就越差。

    注意:

    冗余字段的值在一個(gè)表中修改了,就要想辦法在其他表中更新,否則就會(huì)導(dǎo)致數(shù)據(jù)不一致的問(wèn)題。

    MySQL數(shù)據(jù)庫(kù)cpu飆升到500%的話他怎么處理?

    當(dāng) cpu 飆升到 500%時(shí),先用操作系統(tǒng)命令 top 命令觀察是不是 mysqld 占用導(dǎo)致的,如果不是,找出占用高的進(jìn)程,并進(jìn)行相關(guān)處理。

    如果是 mysqld 造成的, show processlist,看看里面跑的 session 情況,是不是有消耗資源的 sql 在運(yùn)行。找出消耗高的 sql,看看執(zhí)行計(jì)劃是否準(zhǔn)確, index 是否缺失,或者實(shí)在是數(shù)據(jù)量太大造成。

    一般來(lái)說(shuō),肯定要 kill 掉這些線程(同時(shí)觀察 cpu 使用率是否下降),等進(jìn)行相應(yīng)的調(diào)整(比如說(shuō)加索引、改 sql、改內(nèi)存參數(shù))之后,再重新跑這些 SQL。

    也有可能是每個(gè) sql 消耗資源并不多,但是突然之間,有大量的 session 連進(jìn)來(lái)導(dǎo)致 cpu 飆升,這種情況就需要跟應(yīng)用一起來(lái)分析為何連接數(shù)會(huì)激增,再做出相應(yīng)的調(diào)整,比如說(shuō)限制連接數(shù)等

    大表怎么優(yōu)化?某個(gè)表有近千萬(wàn)數(shù)據(jù),CRUD比較慢,如何優(yōu)化?分庫(kù)分表了是怎么做的?分表分庫(kù)了有什么問(wèn)題?有用到中間件么?他們的原理知道么?

    當(dāng)MySQL單表記錄數(shù)過(guò)大時(shí),數(shù)據(jù)庫(kù)的CRUD性能會(huì)明顯下降,一些常見(jiàn)的優(yōu)化措施如下:

  • 限定數(shù)據(jù)的范圍: 務(wù)必禁止不帶任何限制數(shù)據(jù)范圍條件的查詢語(yǔ)句。比如:我們當(dāng)用戶在查詢訂單歷史的時(shí)候,我們可以控制在一個(gè)月的范圍內(nèi)。;
  • 讀/寫分離: 經(jīng)典的數(shù)據(jù)庫(kù)拆分方案,主庫(kù)負(fù)責(zé)寫,從庫(kù)負(fù)責(zé)讀;
  • 緩存: 使用MySQL的緩存,另外對(duì)重量級(jí)、更新少的數(shù)據(jù)可以考慮使用應(yīng)用級(jí)別的緩存;
  • 還有就是通過(guò)分庫(kù)分表的方式進(jìn)行優(yōu)化,主要有垂直分表和水平分表

  • 垂直分區(qū):

    根據(jù)數(shù)據(jù)庫(kù)里面數(shù)據(jù)表的相關(guān)性進(jìn)行拆分。 例如,用戶表中既有用戶的登錄信息又有用戶的基本信息,可以將用戶表拆分成兩個(gè)單獨(dú)的表,甚至放到單獨(dú)的庫(kù)做分庫(kù)。

    簡(jiǎn)單來(lái)說(shuō)垂直拆分是指數(shù)據(jù)表列的拆分,把一張列比較多的表拆分為多張表。 如下圖所示,這樣來(lái)說(shuō)大家應(yīng)該就更容易理解了。

    垂直拆分的優(yōu)點(diǎn): 可以使得行數(shù)據(jù)變小,在查詢時(shí)減少讀取的Block數(shù),減少I/O次數(shù)。此外,垂直分區(qū)可以簡(jiǎn)化表的結(jié)構(gòu),易于維護(hù)。

    垂直拆分的缺點(diǎn): 主鍵會(huì)出現(xiàn)冗余,需要管理冗余列,并會(huì)引起Join操作,可以通過(guò)在應(yīng)用層進(jìn)行Join來(lái)解決。此外,垂直分區(qū)會(huì)讓事務(wù)變得更加復(fù)雜;

    垂直分表

    把主鍵和一些列放在一個(gè)表,然后把主鍵和另外的列放在另一個(gè)表中

    適用場(chǎng)景
    • 1、如果一個(gè)表中某些列常用,另外一些列不常用
    • 2、可以使數(shù)據(jù)行變小,一個(gè)數(shù)據(jù)頁(yè)能存儲(chǔ)更多數(shù)據(jù),查詢時(shí)減少I/O次數(shù)
    缺點(diǎn)
    • 有些分表的策略基于應(yīng)用層的邏輯算法,一旦邏輯算法改變,整個(gè)分表邏輯都會(huì)改變,擴(kuò)展性較差
    • 對(duì)于應(yīng)用層來(lái)說(shuō),邏輯算法增加開(kāi)發(fā)成本
    • 管理冗余列,查詢所有數(shù)據(jù)需要join操作
  • 水平分區(qū):

    保持?jǐn)?shù)據(jù)表結(jié)構(gòu)不變,通過(guò)某種策略存儲(chǔ)數(shù)據(jù)分片。這樣每一片數(shù)據(jù)分散到不同的表或者庫(kù)中,達(dá)到了分布式的目的。 水平拆分可以支撐非常大的數(shù)據(jù)量。

    水平拆分是指數(shù)據(jù)表行的拆分,表的行數(shù)超過(guò)200萬(wàn)行時(shí),就會(huì)變慢,這時(shí)可以把一張的表的數(shù)據(jù)拆成多張表來(lái)存放。舉個(gè)例子:我們可以將用戶信息表拆分成多個(gè)用戶信息表,這樣就可以避免單一表數(shù)據(jù)量過(guò)大對(duì)性能造成影響。

    水品拆分可以支持非常大的數(shù)據(jù)量。需要注意的一點(diǎn)是:分表僅僅是解決了單一表數(shù)據(jù)過(guò)大的問(wèn)題,但由于表的數(shù)據(jù)還是在同一臺(tái)機(jī)器上,其實(shí)對(duì)于提升MySQL并發(fā)能力沒(méi)有什么意義,所以 水平拆分最好分庫(kù)

    水平拆分能夠 支持非常大的數(shù)據(jù)量存儲(chǔ),應(yīng)用端改造也少,但 分片事務(wù)難以解決 ,跨界點(diǎn)Join性能較差,邏輯復(fù)雜。

    《Java工程師修煉之道》的作者推薦 盡量不要對(duì)數(shù)據(jù)進(jìn)行分片,因?yàn)椴鸱謺?huì)帶來(lái)邏輯、部署、運(yùn)維的各種復(fù)雜度 ,一般的數(shù)據(jù)表在優(yōu)化得當(dāng)?shù)那闆r下支撐千萬(wàn)以下的數(shù)據(jù)量是沒(méi)有太大問(wèn)題的。如果實(shí)在要分片,盡量選擇客戶端分片架構(gòu),這樣可以減少一次和中間件的網(wǎng)絡(luò)I/O。

    水平分表:

    表很大,分割后可以降低在查詢時(shí)需要讀的數(shù)據(jù)和索引的頁(yè)數(shù),同時(shí)也降低了索引的層數(shù),提高查詢次數(shù)

    適用場(chǎng)景
    • 1、表中的數(shù)據(jù)本身就有獨(dú)立性,例如表中分表記錄各個(gè)地區(qū)的數(shù)據(jù)或者不同時(shí)期的數(shù)據(jù),特別是有些數(shù)據(jù)常用,有些不常用。
    • 2、需要把數(shù)據(jù)存放在多個(gè)介質(zhì)上。
    水平切分的缺點(diǎn)
    • 1、給應(yīng)用增加復(fù)雜度,通常查詢時(shí)需要多個(gè)表名,查詢所有數(shù)據(jù)都需UNION操作
    • 2、在許多數(shù)據(jù)庫(kù)應(yīng)用中,這種復(fù)雜度會(huì)超過(guò)它帶來(lái)的優(yōu)點(diǎn),查詢時(shí)會(huì)增加讀一個(gè)索引層的磁盤次數(shù)

    下面補(bǔ)充一下數(shù)據(jù)庫(kù)分片的兩種常見(jiàn)方案:

    • 客戶端代理: 分片邏輯在應(yīng)用端,封裝在jar包中,通過(guò)修改或者封裝JDBC層來(lái)實(shí)現(xiàn)。 當(dāng)當(dāng)網(wǎng)的 Sharding-JDBC 、阿里的TDDL是兩種比較常用的實(shí)現(xiàn)。
    • 中間件代理: 在應(yīng)用和數(shù)據(jù)中間加了一個(gè)代理層。分片邏輯統(tǒng)一維護(hù)在中間件服務(wù)中。 我們現(xiàn)在談的 Mycat 、360的Atlas、網(wǎng)易的DDB等等都是這種架構(gòu)的實(shí)現(xiàn)。
  • 分庫(kù)分表后面臨的問(wèn)題

    • 事務(wù)支持 分庫(kù)分表后,就成了分布式事務(wù)了。如果依賴數(shù)據(jù)庫(kù)本身的分布式事務(wù)管理功能去執(zhí)行事務(wù),將付出高昂的性能代價(jià); 如果由應(yīng)用程序去協(xié)助控制,形成程序邏輯上的事務(wù),又會(huì)造成編程方面的負(fù)擔(dān)。

    • 跨庫(kù)join

      只要是進(jìn)行切分,跨節(jié)點(diǎn)Join的問(wèn)題是不可避免的。但是良好的設(shè)計(jì)和切分卻可以減少此類情況的發(fā)生。解決這一問(wèn)題的普遍做法是分兩次查詢實(shí)現(xiàn)。在第一次查詢的結(jié)果集中找出關(guān)聯(lián)數(shù)據(jù)的id,根據(jù)這些id發(fā)起第二次請(qǐng)求得到關(guān)聯(lián)數(shù)據(jù)。 分庫(kù)分表方案產(chǎn)品

    • 跨節(jié)點(diǎn)的count,order by,group by以及聚合函數(shù)問(wèn)題 這些是一類問(wèn)題,因?yàn)樗鼈兌夹枰谌繑?shù)據(jù)集合進(jìn)行計(jì)算。多數(shù)的代理都不會(huì)自動(dòng)處理合并工作。解決方案:與解決跨節(jié)點(diǎn)join問(wèn)題的類似,分別在各個(gè)節(jié)點(diǎn)上得到結(jié)果后在應(yīng)用程序端進(jìn)行合并。和join不同的是每個(gè)結(jié)點(diǎn)的查詢可以并行執(zhí)行,因此很多時(shí)候它的速度要比單一大表快很多。但如果結(jié)果集很大,對(duì)應(yīng)用程序內(nèi)存的消耗是一個(gè)問(wèn)題。

    • 數(shù)據(jù)遷移,容量規(guī)劃,擴(kuò)容等問(wèn)題 來(lái)自淘寶綜合業(yè)務(wù)平臺(tái)團(tuán)隊(duì),它利用對(duì)2的倍數(shù)取余具有向前兼容的特性(如對(duì)4取余得1的數(shù)對(duì)2取余也是1)來(lái)分配數(shù)據(jù),避免了行級(jí)別的數(shù)據(jù)遷移,但是依然需要進(jìn)行表級(jí)別的遷移,同時(shí)對(duì)擴(kuò)容規(guī)模和分表數(shù)量都有限制。總得來(lái)說(shuō),這些方案都不是十分的理想,多多少少都存在一些缺點(diǎn),這也從一個(gè)側(cè)面反映出了Sharding擴(kuò)容的難度。

    • ID問(wèn)題

    • 一旦數(shù)據(jù)庫(kù)被切分到多個(gè)物理結(jié)點(diǎn)上,我們將不能再依賴數(shù)據(jù)庫(kù)自身的主鍵生成機(jī)制。一方面,某個(gè)分區(qū)數(shù)據(jù)庫(kù)自生成的ID無(wú)法保證在全局上是唯一的;另一方面,應(yīng)用程序在插入數(shù)據(jù)之前需要先獲得ID,以便進(jìn)行SQL路由. 一些常見(jiàn)的主鍵生成策略

    UUID 使用UUID作主鍵是最簡(jiǎn)單的方案,但是缺點(diǎn)也是非常明顯的。由于UUID非常的長(zhǎng),除占用大量存儲(chǔ)空間外,最主要的問(wèn)題是在索引上,在建立索引和基于索引進(jìn)行查詢時(shí)都存在性能問(wèn)題。 Twitter的分布式自增ID算法Snowflake 在分布式系統(tǒng)中,需要生成全局UID的場(chǎng)合還是比較多的,twitter的snowflake解決了這種需求,實(shí)現(xiàn)也還是很簡(jiǎn)單的,除去配置信息,核心代碼就是毫秒級(jí)時(shí)間41位 機(jī)器ID 10位 毫秒內(nèi)序列12位。

    • 跨分片的排序分頁(yè)

      般來(lái)講,分頁(yè)時(shí)需要按照指定字段進(jìn)行排序。當(dāng)排序字段就是分片字段的時(shí)候,我們通過(guò)分片規(guī)則可以比較容易定位到指定的分片,而當(dāng)排序字段非分片字段的時(shí)候,情況就會(huì)變得比較復(fù)雜了。為了最終結(jié)果的準(zhǔn)確性,我們需要在不同的分片節(jié)點(diǎn)中將數(shù)據(jù)進(jìn)行排序并返回,并將不同分片返回的結(jié)果集進(jìn)行匯總和再次排序,最后再返回給用戶。如下圖所示:

    MySQL的復(fù)制原理以及流程

    主從復(fù)制:將主數(shù)據(jù)庫(kù)中的DDL和DML操作通過(guò)二進(jìn)制日志(BINLOG)傳輸?shù)綇臄?shù)據(jù)庫(kù)上,然后將這些日志重新執(zhí)行(重做);從而使得從數(shù)據(jù)庫(kù)的數(shù)據(jù)與主數(shù)據(jù)庫(kù)保持一致。

    主從復(fù)制的作用

  • 主數(shù)據(jù)庫(kù)出現(xiàn)問(wèn)題,可以切換到從數(shù)據(jù)庫(kù)。
  • 可以進(jìn)行數(shù)據(jù)庫(kù)層面的讀寫分離。
  • 可以在從數(shù)據(jù)庫(kù)上進(jìn)行日常備份。
  • MySQL主從復(fù)制解決的問(wèn)題

    • 數(shù)據(jù)分布:隨意開(kāi)始或停止復(fù)制,并在不同地理位置分布數(shù)據(jù)備份
    • 負(fù)載均衡:降低單個(gè)服務(wù)器的壓力
    • 高可用和故障切換:幫助應(yīng)用程序避免單點(diǎn)失敗
    • 升級(jí)測(cè)試:可以用更高版本的MySQL作為從庫(kù)

    MySQL主從復(fù)制工作原理

    • 在主庫(kù)上把數(shù)據(jù)更高記錄到二進(jìn)制日志
    • 從庫(kù)將主庫(kù)的日志復(fù)制到自己的中繼日志
    • 從庫(kù)讀取中繼日志的事件,將其重放到從庫(kù)數(shù)據(jù)中

    基本原理流程,3個(gè)線程以及之間的關(guān)聯(lián)

    :binlog線程——記錄下所有改變了數(shù)據(jù)庫(kù)數(shù)據(jù)的語(yǔ)句,放進(jìn)master上的binlog中;

    :io線程——在使用start slave 之后,負(fù)責(zé)從master上拉取 binlog 內(nèi)容,放進(jìn)自己的relay log中;

    :sql執(zhí)行線程——執(zhí)行relay log中的語(yǔ)句;

    復(fù)制過(guò)程

    Binary log:主數(shù)據(jù)庫(kù)的二進(jìn)制日志

    Relay log:從服務(wù)器的中繼日志

    第一步:master在每個(gè)事務(wù)更新數(shù)據(jù)完成之前,將該操作記錄串行地寫入到binlog文件中。

    第二步:salve開(kāi)啟一個(gè)I/O Thread,該線程在master打開(kāi)一個(gè)普通連接,主要工作是binlog dump process。如果讀取的進(jìn)度已經(jīng)跟上了master,就進(jìn)入睡眠狀態(tài)并等待master產(chǎn)生新的事件。I/O線程最終的目的是將這些事件寫入到中繼日志中。

    第三步:SQL Thread會(huì)讀取中繼日志,并順序執(zhí)行該日志中的SQL事件,從而與主數(shù)據(jù)庫(kù)中的數(shù)據(jù)保持一致。

    讀寫分離有哪些解決方案?

    讀寫分離是依賴于主從復(fù)制,而主從復(fù)制又是為讀寫分離服務(wù)的。因?yàn)橹鲝膹?fù)制要求slave不能寫只能讀(如果對(duì)slave執(zhí)行寫操作,那么show slave status將會(huì)呈現(xiàn)Slave_SQL_Running=NO,此時(shí)你需要按照前面提到的手動(dòng)同步一下slave)。

    方案一

    使用mysql-proxy代理

    優(yōu)點(diǎn):直接實(shí)現(xiàn)讀寫分離和負(fù)載均衡,不用修改代碼,master和slave用一樣的帳號(hào),mysql官方不建議實(shí)際生產(chǎn)中使用

    缺點(diǎn):降低性能, 不支持事務(wù)

    方案二

    使用AbstractRoutingDataSource+aop+annotation在dao層決定數(shù)據(jù)源。
    如果采用了mybatis, 可以將讀寫分離放在ORM層,比如mybatis可以通過(guò)mybatis plugin攔截sql語(yǔ)句,所有的insert/update/delete都訪問(wèn)master庫(kù),所有的select 都訪問(wèn)salve庫(kù),這樣對(duì)于dao層都是透明。 plugin實(shí)現(xiàn)時(shí)可以通過(guò)注解或者分析語(yǔ)句是讀寫方法來(lái)選定主從庫(kù)。不過(guò)這樣依然有一個(gè)問(wèn)題, 也就是不支持事務(wù), 所以我們還需要重寫一下DataSourceTransactionManager, 將read-only的事務(wù)扔進(jìn)讀庫(kù), 其余的有讀有寫的扔進(jìn)寫庫(kù)。

    方案三

    使用AbstractRoutingDataSource+aop+annotation在service層決定數(shù)據(jù)源,可以支持事務(wù).

    缺點(diǎn):類內(nèi)部方法通過(guò)this.xx()方式相互調(diào)用時(shí),aop不會(huì)進(jìn)行攔截,需進(jìn)行特殊處理。

    備份計(jì)劃,mysqldump以及xtranbackup的實(shí)現(xiàn)原理

    (1)備份計(jì)劃

    視庫(kù)的大小來(lái)定,一般來(lái)說(shuō) 100G 內(nèi)的庫(kù),可以考慮使用 mysqldump 來(lái)做,因?yàn)?mysqldump更加輕巧靈活,備份時(shí)間選在業(yè)務(wù)低峰期,可以每天進(jìn)行都進(jìn)行全量備份(mysqldump 備份出來(lái)的文件比較小,壓縮之后更小)。

    100G 以上的庫(kù),可以考慮用 xtranbackup 來(lái)做,備份速度明顯要比 mysqldump 要快。一般是選擇一周一個(gè)全備,其余每天進(jìn)行增量備份,備份時(shí)間為業(yè)務(wù)低峰期。

    (2)備份恢復(fù)時(shí)間

    物理備份恢復(fù)快,邏輯備份恢復(fù)慢

    這里跟機(jī)器,尤其是硬盤的速率有關(guān)系,以下列舉幾個(gè)僅供參考

    20G的2分鐘(mysqldump)

    80G的30分鐘(mysqldump)

    111G的30分鐘(mysqldump)

    288G的3小時(shí)(xtra)

    3T的4小時(shí)(xtra)

    邏輯導(dǎo)入時(shí)間一般是備份時(shí)間的5倍以上

    (3)備份恢復(fù)失敗如何處理

    首先在恢復(fù)之前就應(yīng)該做足準(zhǔn)備工作,避免恢復(fù)的時(shí)候出錯(cuò)。比如說(shuō)備份之后的有效性檢查、權(quán)限檢查、空間檢查等。如果萬(wàn)一報(bào)錯(cuò),再根據(jù)報(bào)錯(cuò)的提示來(lái)進(jìn)行相應(yīng)的調(diào)整。

    (4)mysqldump和xtrabackup實(shí)現(xiàn)原理

    mysqldump

    mysqldump 屬于邏輯備份。加入–single-transaction 選項(xiàng)可以進(jìn)行一致性備份。后臺(tái)進(jìn)程會(huì)先設(shè)置 session 的事務(wù)隔離級(jí)別為 RR(SET SESSION TRANSACTION ISOLATION LEVELREPEATABLE READ),之后顯式開(kāi)啟一個(gè)事務(wù)(START TRANSACTION /*!40100 WITH CONSISTENTSNAPSHOT */),這樣就保證了該事務(wù)里讀到的數(shù)據(jù)都是事務(wù)事務(wù)時(shí)候的快照。之后再把表的數(shù)據(jù)讀取出來(lái)。如果加上–master-data=1 的話,在剛開(kāi)始的時(shí)候還會(huì)加一個(gè)數(shù)據(jù)庫(kù)的讀鎖(FLUSH TABLES WITH READ LOCK),等開(kāi)啟事務(wù)后,再記錄下數(shù)據(jù)庫(kù)此時(shí) binlog 的位置(showmaster status),馬上解鎖,再讀取表的數(shù)據(jù)。等所有的數(shù)據(jù)都已經(jīng)導(dǎo)完,就可以結(jié)束事務(wù)

    Xtrabackup:

    xtrabackup 屬于物理備份,直接拷貝表空間文件,同時(shí)不斷掃描產(chǎn)生的 redo 日志并保存下來(lái)。最后完成 innodb 的備份后,會(huì)做一個(gè) flush engine logs 的操作(老版本在有 bug,在5.6 上不做此操作會(huì)丟數(shù)據(jù)),確保所有的 redo log 都已經(jīng)落盤(涉及到事務(wù)的兩階段提交

    概念,因?yàn)?xtrabackup 并不拷貝 binlog,所以必須保證所有的 redo log 都落盤,否則可能會(huì)丟最后一組提交事務(wù)的數(shù)據(jù))。這個(gè)時(shí)間點(diǎn)就是 innodb 完成備份的時(shí)間點(diǎn),數(shù)據(jù)文件雖然不是一致性的,但是有這段時(shí)間的 redo 就可以讓數(shù)據(jù)文件達(dá)到一致性(恢復(fù)的時(shí)候做的事

    情)。然后還需要 flush tables with read lock,把 myisam 等其他引擎的表給備份出來(lái),備份完后解鎖。這樣就做到了完美的熱備。

    數(shù)據(jù)表?yè)p壞的修復(fù)方式有哪些?

    使用 myisamchk 來(lái)修復(fù),具體步驟:

    • 1)修復(fù)前將mysql服務(wù)停止。
    • 2)打開(kāi)命令行方式,然后進(jìn)入到mysql的/bin目錄。
    • 3)執(zhí)行myisamchk –recover 數(shù)據(jù)庫(kù)所在路徑/*.MYI

    使用repair table 或者 OPTIMIZE table命令來(lái)修復(fù),REPAIR TABLE table_name 修復(fù)表 OPTIMIZE TABLE table_name 優(yōu)化表 REPAIR TABLE 用于修復(fù)被破壞的表。 OPTIMIZE TABLE 用于回收閑置的數(shù)據(jù)庫(kù)空間,當(dāng)表上的數(shù)據(jù)行被刪除時(shí),所占據(jù)的磁盤空間并沒(méi)有立即被回收,使用了OPTIMIZE TABLE命令后這些空間將被回收,并且對(duì)磁盤上的數(shù)據(jù)行進(jìn)行重排(注意:是磁盤上,而非數(shù)據(jù)庫(kù))

    總結(jié)

    以上是生活随笔為你收集整理的MySQL数据库面试题(2020最新版)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。