面試之?dāng)?shù)據(jù)庫篇

作者:我沒有三顆心臟
鏈接:http://m.itdecent.cn/p/71927a377dc6
來源:簡書

1. left join 與 inner join的區(qū)別

sql的left join 、right join 、inner join之間的區(qū)別

  1. left join(左聯(lián)接) 返回包括左表中的所有記錄和右表中聯(lián)結(jié)字段相等的記錄
  2. right join(右聯(lián)接) 返回包括右表中的所有記錄和左表中聯(lián)結(jié)字段相等的記錄
  3. inner join(等值連接) 只返回兩個表中聯(lián)結(jié)字段相等的行

left join sql語句如下:
select * from Aleft join B on A.aid = B.bid
left join是以A表的記錄為基礎(chǔ)的,A可以看成左表,B可以看成右表,left join是以左表為準(zhǔn)的.換句話說,左表(A)的記錄將會全部表示出來,而右表(B)只會顯示符合搜索條件的記錄(例子中為: A.aid = B.bid)。B表不符合查詢要求的地方均為NULL。
right join sql語句如下:
select * from A right join B on A.aid = B.bid
仔細(xì)觀察一下,就會發(fā)現(xiàn),和left join的結(jié)果剛好相反,這次是以右表(B)為基礎(chǔ)的,A表不符合連接要求的地方用NULL填充.
inner join sql語句如下:
select * from A inner join B on A.aid = B.bid
很明顯,這里只顯示出了 A.aID = B.bID的記錄.這說明inner join并不以誰為基礎(chǔ),它只顯示符合條件的記錄。不符合要求的則舍去。

2.事務(wù)的簡單理解

事務(wù)簡單來說:一個 Session 中所進(jìn)行所有的操作,要么同時成功,要么同時失??;作為單個邏輯工作單元執(zhí)行的一系列操作,滿足四大特性:

  1. 原子性(Atomicity):事務(wù)作為一個整體被執(zhí)行 ,要么全部執(zhí)行,要么全部不執(zhí)行
  2. 一致性(Consistency):保證數(shù)據(jù)庫狀態(tài)從一個一致狀態(tài)轉(zhuǎn)變?yōu)榱硪粋€一致狀態(tài)
  3. 隔離性(Isolation):多個事務(wù)并發(fā)執(zhí)行時,一個事務(wù)的執(zhí)行不應(yīng)影響其他事務(wù)的執(zhí)行
  4. 持久性(Durability):一個事務(wù)一旦提交,對數(shù)據(jù)庫的修改應(yīng)該永久保存

并發(fā)性問題:

  1. 丟失更新:一個事務(wù)的更新覆蓋了另一個事務(wù)的更新;
  2. 臟讀:一個事務(wù)讀取了另一個事務(wù)未提交的數(shù)據(jù);
  3. 不可重復(fù)讀:不可重復(fù)讀的重點(diǎn)是修改,同樣條件下兩次讀取結(jié)果不同,也就是說,被讀取的數(shù)據(jù)可以被其它事務(wù)修改;
  4. 幻讀:幻讀的重點(diǎn)在于新增或者刪除,同樣條件下兩次讀出來的記錄數(shù)不一樣。

3.事務(wù)隔離級別

隔離級別決定了一個session中的事務(wù)可能對另一個session中的事務(wù)的影響。ANSI標(biāo)準(zhǔn)定義了4個隔離級別,MySQL的InnoDB都支持,分別是:

  1. 讀未提交(READ UNCOMMITTED):最低級別的隔離,通常又稱為dirty read,它允許一個事務(wù)讀取另一個事務(wù)還沒 commit 的數(shù)據(jù),這樣可能會提高性能,但是會導(dǎo)致臟讀問題;
  2. 讀已提交(READ COMMITTED):在一個事務(wù)中只允許對其它事務(wù)已經(jīng) commit 的記錄可見,該隔離級別不能避免不可重復(fù)讀問題;
  3. 可重復(fù)讀(REPEATABLE READ):在一個事務(wù)開始后,其他事務(wù)對數(shù)據(jù)庫的修改在本事務(wù)中不可見,直到本事務(wù) commit 或 rollback。但是,其他事務(wù)的 insert/delete 操作對該事務(wù)是可見的,也就是說,該隔離級別并不能避免幻讀問題。在一個事務(wù)中重復(fù) select 的結(jié)果一樣,除非本事務(wù)中 update 數(shù)據(jù)庫。
  4. 序列化(SERIALIZABLE):最高級別的隔離,只允許事務(wù)串行執(zhí)行。
    MySQL默認(rèn)的隔離級別是可重復(fù)讀(REPEATABLE READ)

MySQL的事務(wù)支持不是綁定在MySQL服務(wù)器本身,而是與存儲引擎相關(guān):

  • MyISAM:不支持事務(wù),用于只讀程序提高性能;
  • InnoDB:支持ACID事務(wù)、行級鎖、并發(fā);
  • Berkeley DB:支持事務(wù)。

4.事務(wù)提交模式

  • 自動提交模式
    默認(rèn)方式,每執(zhí)行完一條SQL語句就自動提交事務(wù),每條SQL語句的執(zhí)行都被單獨(dú)提交,因此一個事務(wù)只有一條SQL語句組成。
  • 手動提交模式
    通常一個新的數(shù)據(jù)庫連接產(chǎn)生,便意味著一個新的事務(wù)生成。我們要將一個整體操作設(shè)置為一個事務(wù),而不是一條SQL語句當(dāng)成一個事務(wù)。
    Conncetion.setAutoCommit(false):設(shè)置為手動提交模式
    Connection.commit():提交事務(wù)
    Connection.rollback():回滾事務(wù)
    一個事務(wù)中可以包含若干條SQL語句
    // 開啟事務(wù),對數(shù)據(jù)的操作就不會立即生效。
    connection.setAutoCommit(false);

    // A賬戶減去500塊
    String sql = "UPDATE a SET money=money-500 ";
    preparedStatement = connection.prepareStatement(sql);
    preparedStatement.executeUpdate();

    // 在轉(zhuǎn)賬過程中出現(xiàn)問題
    int a = 3 / 0;

    // B賬戶多500塊
    String sql2 = "UPDATE b SET money=money+500";
    preparedStatement = connection.prepareStatement(sql2);
    preparedStatement.executeUpdate();

    // 如果程序能執(zhí)行到這里,沒有拋出異常,我們就提交數(shù)據(jù)
    connection.commit();

    // 關(guān)閉事務(wù)【自動提交】
    connection.setAutoCommit(true);

} catch(SQLException e) {
    try {
        // 如果出現(xiàn)了異常,就會進(jìn)到這里來,我們就把事務(wù)回滾【將數(shù)據(jù)變成原來那樣】
        connection.rollback();

        // 關(guān)閉事務(wù)【自動提交】
        connection.setAutoCommit(true);
    } catch (SQLException e1) {
        e1.printStackTrace();
    }
}

5.分布式事務(wù)其中一個事務(wù)出錯

XA模式

6.三大范式

  1. 第一范式: 列不可分
    1NF(第一范式)是對屬性具有原子性的要求,不可再分
  2. 第二范式: 消除非主屬性對碼的部分函數(shù)依賴
    2NF(第二范式)是對記錄有唯一性的要求,即實(shí)體的唯一性,不存在部分依賴,每一列與主鍵都相關(guān)
  3. 第三范式: 消除非主屬性對碼的傳遞函數(shù)依賴
    3NF(第三范式)對字段有冗余性的要求,任何字段不能由其他字段派生出來,它要求字段沒有冗余,即不存在依賴傳遞

7.索引

  1. 什么是索引
    索引會影響到where后面的查找和order by后面的排序
  2. 聚集索引和非聚集索引
  • 非聚集索引:字典的檢索或者書的目錄(數(shù)據(jù)與索引分開)
  • 聚集索引:頁碼下面的數(shù)字(頁碼在需要查找的數(shù)據(jù)的里面)
  1. 底層數(shù)據(jù)結(jié)構(gòu)是什么,為什么使用這種數(shù)據(jù)結(jié)構(gòu)?
    MyIsam使用的是B+tree(多路查找樹)索引,既有索引列的值也有指向數(shù)據(jù)行的指針,使用二分法查找,時間復(fù)雜度為O(logn),構(gòu)建出的索引樹如圖(非聚集索引)
    MyIsam在物理上有三個文件組成:
  • MYI:存儲索引
  • MYD:存儲數(shù)據(jù)
  • FRM:表結(jié)構(gòu)
    因此MyISAM中索引檢索的算法為首先按照B+Tree搜索算法搜索索引,如果指定的Key存在,則取出其data域的值,然后以data域的值為地址,讀取相應(yīng)數(shù)據(jù)記錄。


    image.png

    image.png

InnoDB使用的是B+tree做的索引。InnoDB的數(shù)據(jù)文件本身就是索引文件。在InnoDB中,表數(shù)據(jù)文件本身就是按B+Tree組織的一個索引結(jié)構(gòu),這棵樹的葉節(jié)點(diǎn)data域保存了完整的數(shù)據(jù)記錄。這個索引的key是數(shù)據(jù)表的主鍵,因此InnoDB表數(shù)據(jù)文件本身就是主索引。

image.png

InnoDB的數(shù)據(jù)文件本身要按主鍵聚集(只有一個聚集索引),所以InnoDB要求表必須有主鍵。默認(rèn)會拿主鍵(id)作為聚集索引。如果沒有主鍵會取非空唯一的作為聚集索引。如果都沒有InnoDB會自己維護(hù)一個唯一id來作為聚集索引。
InnoDB的輔助索引data域存儲相應(yīng)記錄主鍵的值而不是地址。換句話說,InnoDB的所有輔助索引都引用主鍵作為data域。

image.png

這里以英文字符的ASCII碼作為比較準(zhǔn)則。聚集索引這種實(shí)現(xiàn)方式使得按主鍵的搜索十分高效,但是輔助索引搜索需要檢索兩遍索引:首先檢索輔助索引獲得主鍵,然后用主鍵到主索引中檢索獲得記錄。

了解不同存儲引擎的索引實(shí)現(xiàn)方式對于正確使用和優(yōu)化索引都非常有幫助,例如知道了InnoDB的索引實(shí)現(xiàn)后,就很容易明白為什么不建議使用過長的字段作為主鍵,因?yàn)樗休o助索引都引用主索引,過長的主索引會令輔助索引變得過大。再例如,用非單調(diào)的字段作為主鍵在InnoDB中不是個好主意,因?yàn)镮nnoDB數(shù)據(jù)文件本身是一顆B+Tree,非單調(diào)的主鍵會造成在插入新記錄時數(shù)據(jù)文件為了維持B+Tree的特性而頻繁的分裂調(diào)整,十分低效,而使用自增字段作為主鍵則是一個很好的選擇。

  1. 索引的優(yōu)缺點(diǎn),建索引的原則
    優(yōu)點(diǎn): 提高檢索速度,降低磁盤的IO次數(shù)
    缺點(diǎn): 索引需要存儲,需要空間,索引實(shí)際上是一張表,字段更新會有性能損耗

適合:

  • 頻繁作為where條件的字段(where id = ?)
  • 關(guān)聯(lián)字段可以建索引,例如外鍵字段
  • Order by 的 column,Group by 的 column(排序)

不適合:

  • Where條件中用不到的字段
  • 頻繁更新的字段
  • 數(shù)據(jù)值分布均勻(男,女,真假值)
  • 表數(shù)量可以確定行數(shù),且數(shù)據(jù)量不是很大

原則:
一個最重要的原則是最左前綴原理,在提這個之前要先說下聯(lián)合索引,MySQL中的索引可以以一定順序引用多個列,這種索引叫做聯(lián)合索引,一般的,一個聯(lián)合索引是一個有序元組<a1, a2, …, an>,其中各個元素均為數(shù)據(jù)表的一列。另外,單列索引可以看成聯(lián)合索引元素數(shù)為1的特例。

- 那么查詢的時候,如果查詢【A】【A,B】 【A,B,C】,那么可以通過索引查詢
- 如果查詢的時候,采用【A,C】,那么C這個雖然是索引,但是由于中間缺失了B,因此C這個索引是用不到的,只能用到A索引
- 如果查詢的時候,采用【B】 【B,C】 【C】,由于沒有用到第一列索引,不是最左前綴,那么后面的索引也是用不到了
- 如果查詢的時候,采用范圍查詢,并且是最左前綴,也就是第一列索引,那么可以用到索引,但是范圍后面的列無法用到索引

索引失效:
Select * from user order by age 索引生效
Index(name,age) 復(fù)合索引(建索引最好用復(fù)合索引)
Select * from user oder by age 索引失效
因?yàn)榉纤饕蒼ame,age組成前面部分是name,不能跨越name直接到age
Select * from user oder by name,age 索引生效
Select * from user where age = 18 and name = 'zsj'索引失效
Index(age,name) 復(fù)合索引
Select * from user where age>18 and name = 'zsj' age用上索引后面失效

  1. 行鎖和表鎖
    在執(zhí)行sql語句,如
update table set c1 = ? where c2 = ?  會檢索出一行或者幾行數(shù)據(jù)

在InnoDB中檢索出的這幾行會被鎖住,此刻其他線程只能等待,提交后其他線程才能訪問(行鎖)

8.什么是視圖?使用視圖的場景

視圖是一種虛擬的表,具有和物理表相同的功能。可以對視圖進(jìn)行增,改,查,操作,視圖通常是有一個表或者多個表的行或列的子集。對視圖的修改不影響基本表。它使得我們獲取數(shù)據(jù)更容易,相比多表查詢。

  1. 不希望訪問者獲取整個表的信息,只暴露部分字段給訪問者,所以就建一個虛表,就是視圖。
  2. 查詢的數(shù)據(jù)來源于不同的表,而查詢者希望以統(tǒng)一的方式查詢,這樣也可以建立一個視圖,把多個表查詢結(jié)果聯(lián)合起來,查詢者只需要直接從視圖中獲取數(shù)據(jù),不必考慮數(shù)據(jù)來源于不同表所帶來的差異。

注意:這個視圖是在數(shù)據(jù)庫中創(chuàng)建的 而不是用代碼創(chuàng)建的。

9.DDL與DML

DML數(shù)據(jù)操縱語言:就是我們最經(jīng)常用到的 SELECT、UPDATE、INSERT、DELETE。 主要用來對數(shù)據(jù)庫的數(shù)據(jù)進(jìn)行一些操作。
DDL數(shù)據(jù)庫定義語言:其實(shí)就是我們在創(chuàng)建表的時候用到的一些sql,比如說:CREATE、ALTER、DROP等。DDL主要是用在定義或改變表的結(jié)構(gòu),數(shù)據(jù)類型,表之間的鏈接和約束等初始化工作上。
truncate table:
屬于DDL(Data Definition Language,數(shù)據(jù)庫定義語言)
不可回滾
不可帶 where
表內(nèi)容刪除
刪除速度快
保留表而刪除所有數(shù)據(jù)的時候用truncate

10.數(shù)據(jù)庫悲觀鎖和樂觀鎖

數(shù)據(jù)庫管理系統(tǒng)(DBMS)中的并發(fā)控制的任務(wù)是確保在多個事務(wù)同時存取數(shù)據(jù)庫中同一數(shù)據(jù)時不破壞事務(wù)的隔離性和統(tǒng)一性以及數(shù)據(jù)庫的統(tǒng)一性。

樂觀并發(fā)控制(樂觀鎖)和悲觀并發(fā)控制(悲觀鎖)是并發(fā)控制主要采用的技術(shù)手段。

  1. MySQL InnoDB中使用悲觀鎖:
    要使用悲觀鎖,我們必須關(guān)閉mysql數(shù)據(jù)庫的自動提交屬性,因?yàn)镸ySQL默認(rèn)使用autocommit模式,也就是說,當(dāng)你執(zhí)行一個更新操作后,MySQL會立刻將結(jié)果進(jìn)行提交。 set autocommit=0;
//0.開始事務(wù)
begin;/begin work;/start transaction; (三者選一就可以)
//1.查詢出商品信息
select status from t_goods where id=1 for update;
//2.根據(jù)商品信息生成訂單
insert into t_orders (id,goods_id) values (null,1);
//3.修改商品status為2
update t_goods set status=2;
//4.提交事務(wù)
commit;/commit work;

上面的查詢語句中,我們使用了 select…for update 的方式,這樣就通過開啟排他鎖的方式實(shí)現(xiàn)了悲觀鎖。此時在t_goods表中,id為1的 那條數(shù)據(jù)就被我們鎖定了,其它的事務(wù)必須等本次事務(wù)提交之后才能執(zhí)行。這樣我們可以保證當(dāng)前的數(shù)據(jù)不會被其它事務(wù)修改。
上面我們提到,使用 select…for update 會把數(shù)據(jù)給鎖住,不過我們需要注意一些鎖的級別,MySQL InnoDB默認(rèn)行級鎖。行級鎖都是基于索引的,如果一條SQL語句用不到索引是不會使用行級鎖的,會使用表級鎖把整張表鎖住,這點(diǎn)需要注意。

優(yōu)點(diǎn)與不足:
悲觀并發(fā)控制實(shí)際上是“先取鎖再訪問”的保守策略,為數(shù)據(jù)處理的安全提供了保證。但是在效率方面,處理加鎖的機(jī)制會讓數(shù)據(jù)庫產(chǎn)生額外的開銷,還有增加產(chǎn)生死鎖的機(jī)會;另外,在只讀型事務(wù)處理中由于不會產(chǎn)生沖突,也沒必要使用鎖,這樣做只能增加系統(tǒng)負(fù)載;還有會降低了并行性,一個事務(wù)如果鎖定了某行數(shù)據(jù),其他事務(wù)就必須等待該事務(wù)處理完才可以處理那行數(shù)

2.樂觀鎖:假設(shè)不會發(fā)生并發(fā)沖突,只在提交操作時檢查是否違反數(shù)據(jù)完整性。
樂觀鎖是一種不會阻塞其他線程并發(fā)的控制,它不會使用數(shù)據(jù)庫的鎖進(jìn)行實(shí)現(xiàn),它的設(shè)計里面由于不阻塞其他線程,所以并不會引起線程頻繁掛起和恢復(fù),這樣便能夠提高并發(fā)能力,所以也有人把它稱為非阻塞鎖。一般的實(shí)現(xiàn)樂觀鎖的方式就是記錄數(shù)據(jù)版本。
數(shù)據(jù)版本,為數(shù)據(jù)增加的一個版本標(biāo)識。當(dāng)讀取數(shù)據(jù)時,將版本標(biāo)識的值一同讀出,數(shù)據(jù)每更新一次,同時對版本標(biāo)識進(jìn)行更新。當(dāng)我們提交更新的時候,判斷數(shù)據(jù)庫表對應(yīng)記錄的當(dāng)前版本信息與第一次取出來的版本標(biāo)識進(jìn)行比對,如果數(shù)據(jù)庫表當(dāng)前版本號與第一次取出來的版本標(biāo)識值相等,則予以更新,否則認(rèn)為是過期數(shù)據(jù)。
實(shí)現(xiàn)數(shù)據(jù)版本有兩種方式,第一種是使用版本號,第二種是使用時間戳。

優(yōu)點(diǎn)與不足:
樂觀并發(fā)控制相信事務(wù)之間的數(shù)據(jù)競爭(data race)的概率是比較小的,因此盡可能直接做下去,直到提交的時候才去鎖定,所以不會產(chǎn)生任何鎖和死鎖。但如果直接簡單這么做,還是有可能會遇到不可預(yù)期的結(jié)果,例如兩個事務(wù)都讀取了數(shù)據(jù)庫的某一行,經(jīng)過修改以后寫回數(shù)據(jù)庫,這時就遇到了問題。

11.SQL約束有幾種

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

12.MySQL存儲引擎中的MyISAM和InnoDB區(qū)別詳解

在MySQL 5.5之前,MyISAM是mysql的默認(rèn)數(shù)據(jù)庫引擎,其由早期的ISAM(Indexed Sequential Access Method:有索引的順序訪問方法)所改良。雖然MyISAM性能極佳,但卻有一個顯著的缺點(diǎn):不支持事務(wù)處理。不過,MySQL也導(dǎo)入了另一種數(shù)據(jù)庫引擎InnoDB,以強(qiáng)化參考完整性與并發(fā)違規(guī)處理機(jī)制,后來就逐漸取代MyISAM。
InnoDB是MySQL的數(shù)據(jù)庫引擎之一,其由Innobase oy公司所開發(fā),2006年五月由甲骨文公司并購。與傳統(tǒng)的ISAM、MyISAM相比,InnoDB的最大特色就是支持ACID兼容的事務(wù)功能,類似于PostgreSQL。目前InnoDB采用雙軌制授權(quán),一是GPL授權(quán),另一是專有軟件授權(quán)。具體地,MyISAM與InnoDB作為MySQL的兩大存儲引擎的差異主要包括:

13.varchar和char的區(qū)別

  1. char是一種固定長度的類型,varchar是一種可變長度的類型,
    例如:
    定義一個char[10]和varchar[10],如果存進(jìn)去的是 'test',那么char所占的長度依然為10,除了字符 'test' 外,后面跟六個空格,varchar就立馬把長度變?yōu)?了,取數(shù)據(jù)的時候,char類型的要用trim()去掉多余的空格,而varchar是不需要的
  2. char的存取速度還是要比varchar要快得多,因?yàn)槠溟L度固定,方便程序的存儲于查找
    char也為此付出的是空間的代價,因?yàn)槠溟L度固定,所以難免會有多余的空格占位符占據(jù)空間,可謂是以空間換取時間效率。
  3. varchar是以空間效率為首位。
    char的存儲方式是:對英文字符(ASCII)占用1個字節(jié),對一個漢字占用兩個字節(jié)。
    varchar的存儲方式是:對每個英文字符占用2個字節(jié),漢字也占用2個字節(jié)。
    兩者的存儲數(shù)據(jù)都非unicode的字符數(shù)據(jù)。

14. IN 和 EXISTS 的區(qū)別及應(yīng)用

select * from Awhere id in(select id from B)
以上查詢使用了in語句,in()只執(zhí)行一次,它查出B表中的所有id字段并緩存起來.之后,檢查A表的id是否與B表中的id相等,如果相等則將A表的記錄加入結(jié)果集中,直到遍歷完A表的所有記錄.它的查詢過程類似于以下過程

List resultSet=[];
Array A=(select * from A);
Array B=(select id from B);
for(int i=0;i<A.length;i++) {
   for(int j=0;j<B.length;j++) {
      if(A[i].id==B[j].id) {
         resultSet.add(A[i]);
         break;
      }
   }
}return resultSet;

可以看出,當(dāng)B表數(shù)據(jù)較大時不適合使用in(),因?yàn)樗鼤﨎表數(shù)據(jù)全部遍歷一次.
如:A表有10000條記錄,B表有1000000條記錄,那么最多有可能遍歷100001000000次,效率很差.
再如:A表有10000條記錄,B表有100條記錄,那么最多有可能遍歷10000
100次,遍歷次數(shù)大大減少,效率大大提升.結(jié)論:in()適合B表比A表數(shù)據(jù)小的情況

select a.* from A a where exists(select 1 from B b where a.id=b.id)
以上查詢使用了exists語句,exists()會執(zhí)行A.length次,它并不緩存exists()結(jié)果集,因?yàn)閑xists()結(jié)果集的內(nèi)容并不重要,重要的是結(jié)果集中是否有記錄,如果有則返回true,沒有則返回false.
它的查詢過程類似于以下過程

List resultSet=[];
Array A=(select * from A)
for(int i=0;i<A.length;i++) {
   if(exists(A[i].id) {
    執(zhí)行select 1 from B b where b.id=a.id是否有記錄返回
       resultSet.add(A[i]);
   }
}return resultSet;

當(dāng)B表比A表數(shù)據(jù)大時適合使用exists(),因?yàn)樗鼪]有那么遍歷操作,只需要再執(zhí)行一次查詢就行。
如:A表有10000條記錄,B表有1000000條記錄,那么exists()會執(zhí)行10000次去判斷A表中的id是否與B表中的id相等。
如:A表有10000條記錄,B表有100000000條記錄,那么exists()還是執(zhí)行10000次,因?yàn)樗粓?zhí)行A.length次,可見B表數(shù)據(jù)越多,越適合exists()發(fā)揮效果。
再如:A表有10000條記錄,B表有100條記錄,那么exists()還是執(zhí)行10000次,還不如使用in()遍歷10000*100次,因?yàn)閕n()是在內(nèi)存里遍歷比較,而exists()需要查詢數(shù)據(jù)庫,我們都知道查詢數(shù)據(jù)庫所消耗的性能更高,而內(nèi)存比較很快.
結(jié)論:exists()適合B表比A表數(shù)據(jù)大的情況當(dāng)A表數(shù)據(jù)與B表數(shù)據(jù)一樣大時,in與exists效率差不多,可任選一個使用.

15.優(yōu)化MySQL

  1. 通過explain查詢和分析SQL的執(zhí)行計劃:
    使用 EXPLAIN 關(guān)鍵字可以知道MySQL是如何處理你的SQL語句的,以便分析查詢語句或是表結(jié)構(gòu)的性能瓶頸。通過explain命令可以得到表的讀取順序、數(shù)據(jù)讀取操作的操作類型、哪些索引可以使用、哪些索引被實(shí)際使用、表之間的引用以及每張表有多少行被優(yōu)化器查詢等問題。當(dāng)擴(kuò)展列extra出現(xiàn)Using filesort和Using temporay,則往往表示SQL需要優(yōu)化了。

多數(shù)來源:
簡書:我沒有三顆心臟
掘金:吳德寶AllenWu MySQL索引和SQL調(diào)優(yōu)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容