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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

互联网公司面试必问的mysql题目(下)

發布時間:2025/7/14 数据库 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 互联网公司面试必问的mysql题目(下) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

這是mysql系列的下篇,上篇文章地址我附在文末。

什么是數據庫索引?索引有哪幾種類型?什么是最左前綴原則?索引算法有哪些?有什么區別?

索引是對數據庫表中一列或多列的值進行排序的一種結構。一個非常恰當的比喻就是書的目錄頁與書的正文內容之間的關系,為了方便查找書中的內容,通過對內容建立索引形成目錄。索引是一個文件,它是要占據物理空間的。

主鍵索引:
數據列不允許重復,不允許為NULL.一個表只能有一個主鍵。

唯一索引:
數據列不允許重復,允許為NULL值,一個表允許多個列創建唯一索引。

可以通過
ALTER TABLE table_name ADD UNIQUE (column);
創建唯一索引

可以通過
ALTER TABLE table_name ADD UNIQUE (column1,column2);
創建唯一組合索引

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

可以通過ALTER TABLE table_name ADD INDEX index_name (column);創建普通索引

可以通過ALTER TABLE table_name ADD INDEX index_name(column1, column2, column3);創建組合索引

全文索引:
是目前搜索引擎使用的一種關鍵技術。

可以通過ALTER TABLE table_name ADD FULLTEXT (column);創建全文索引

最左前綴

  • 顧名思義,就是最左優先,在創建多列索引時,要根據業務需求,where子句中使用最頻繁的一列放在最左邊。
  • 還有一個就是生效原則 比如
index(a,b,c) where a=3 是,只使用了a where a=3 and b=5 是,使用了a,b where a=3 and b=5 and c=4 是,使用了a,b,c where b=3 or where c=4 否 where a=3 and c=4 是,僅使用了a where a=3 and b>10 and c=7 是,使用了a,b where a=3 and b like '%xx%' and c=7 使用了a,b

索引算法有 BTree Hash

BTree是最常用的mysql數據庫索引算法,也是mysql默認的算法。因為它不僅可以被用在=,>,>=,<,<=和between這些比較操作符上,而且還可以用于like操作符,只要它的查詢條件是一個不以通配符開頭的常量,
例如:
select * from user where name like 'jack%';
如果一通配符開頭,或者沒有使用常量,則不會使用索引,例如:
select * from user where name like '%jack';

Hash
Hash索引只能用于對等比較,例如=,<=>(相當于=)操作符。由于是一次定位數據,不像BTree索引需要從根節點到枝節點,最后才能訪問到頁節點這樣多次IO訪問,所以檢索效率遠高于BTree索引。

BTree索引是最常用的mysql數據庫索引算法,也是mysql默認的算法。因為它不僅可以被用在=,>,>=,<,<=和between這些比較操作符上,而且還可以用于like操作符
例如:

只要它的查詢條件是一個不以通配符開頭的常量 select * from user where name like 'jack%'; 如果一通配符開頭,或者沒有使用常量,則不會使用索引,例如: select * from user where name like '%jack';

Hash
Hash索引只能用于對等比較,例如=,<=>(相當于=)操作符。由于是一次定位數據,不像BTree索引需要從根節點到枝節點,最后才能訪問到頁節點這樣多次IO訪問,所以檢索效率遠高于BTree索引。

索引設計的原則?

  • 適合索引的列是出現在where子句中的列,或者連接子句中指定的列
  • 基數較小的類,索引效果較差,沒有必要在此列建立索引
  • 使用短索引,如果對長字符串列進行索引,應該指定一個前綴長度,這樣能夠節省大量索引空間
  • 不要過度索引。索引需要額外的磁盤空間,并降低寫操作的性能。在修改表內容的時候,索引會進行更新甚至重構,索引列越多,這個時間就會越長。所以只保持需要的索引有利于查詢即可。
  • 如何定位及優化SQL語句的性能問題

    對于低性能的SQL語句的定位,最重要也是最有效的方法就是使用執行計劃。
    我們知道,不管是哪種數據庫,或者是哪種數據庫引擎,在對一條SQL語句進行執行的過程中都會做很多相關的優化,對于查詢語句,最重要的優化方式就是使用索引。
    而執行計劃,就是顯示數據庫引擎對于SQL語句的執行的詳細情況,其中包含了是否使用索引,使用什么索引,使用的索引的相關信息等。

    執行計劃包含的信息
    id
    有一組數字組成。表示一個查詢中各個子查詢的執行順序;

    • id相同執行順序由上至下。
    • id不同,id值越大優先級越高,越先被執行。
    • id為null時表示一個結果集,不需要使用它查詢,常出現在包含union等查詢語句中。

    select_type
    每個子查詢的查詢類型,一些常見的查詢類型。

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

    table
    查詢的數據表,當從衍生表中查數據時會顯示 x 表示對應的執行計劃id
    partitions
    表分區、表創建的時候可以指定通過那個列進行表分區。 舉個例子:

    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(非常重要,可以看到有沒有走索引)
    訪問類型

    • ALL 掃描全表數據
    • index 遍歷索引
    • range 索引范圍查找
    • index_subquery 在子查詢中使用 ref
    • unique_subquery 在子查詢中使用 eq_ref
    • ref_or_null 對Null進行索引的優化的 ref
    • fulltext 使用全文索引
    • ref 使用非唯一索引查找數據
    • eq_ref 在join查詢中使用PRIMARY KEYorUNIQUE NOT NULL索引關聯。

    possible_keys
    可能使用的索引,注意不一定會使用。查詢涉及到的字段上若存在索引,則該索引將被列出來。當該列為 NULL時就要考慮當前的SQL是否需要優化了。
    key
    顯示MySQL在查詢中實際使用的索引,若沒有使用索引,顯示為NULL。

    TIPS:查詢中若使用了覆蓋索引(覆蓋索引:索引的數據覆蓋了需要查詢的所有數據),則該索引僅出現在key列表中
    key_length
    索引長度
    ref
    表示上述表的連接匹配條件,即哪些列或常量被用于查找索引列上的值
    rows
    返回估算的結果集數目,并不是一個準確的值。
    extra
    extra的信息非常豐富,常見的有:
    1.Using index 使用覆蓋索引
    2.Using where 使用了用where子句來過濾結果集
    3.Using filesort 使用文件排序,使用非索引列進行排序時出現,非常消耗性能,盡量優化。
    4.Using temporary 使用了臨時表
    sql優化的目標可以參考阿里開發手冊

    某個表有近千萬數據,CRUD比較慢,如何優化?分庫分表了是怎么做的?分表分庫了有什么問題?有用到中間件么?他們的原理知道么?

    數據千萬級別之多,占用的存儲空間也比較大,可想而知它不會存儲在一塊連續的物理空間上,而是鏈式存儲在多個碎片的物理空間上。可能對于長字符串的比較,就用更多的時間查找與比較,這就導致用更多的時間。

    • 可以做表拆分,減少單表字段數量,優化表結構。
    • 在保證主鍵有效的情況下,檢查主鍵索引的字段順序,使得查詢語句中條件的字段順序和主鍵索引的字段順序保持一致。

    主要兩種拆分 垂直拆分,水平拆分。

    垂直分表

    也就是“大表拆小表”,基于列字段進行的。一般是表中的字段較多,將不常用的, 數據較大,長度較長(比如text類型字段)的拆分到“擴展表“。 一般是針對那種幾百列的大表,也避免查詢時,數據量太大造成的“跨頁”問題。

    垂直分庫針對的是一個系統中的不同業務進行拆分,比如用戶User一個庫,商品Producet一個庫,訂單Order一個庫。 切分后,要放在多個服務器上,而不是一個服務器上。為什么? 我們想象一下,一個購物網站對外提供服務,會有用戶,商品,訂單等的CRUD。沒拆分之前, 全部都是落到單一的庫上的,這會讓數據庫的單庫處理能力成為瓶頸。按垂直分庫后,如果還是放在一個數據庫服務器上, 隨著用戶量增大,這會讓單個數據庫的處理能力成為瓶頸,還有單個服務器的磁盤空間,內存,tps等非常吃緊。 所以我們要拆分到多個服務器上,這樣上面的問題都解決了,以后也不會面對單機資源問題。

    數據庫業務層面的拆分,和服務的“治理”,“降級”機制類似,也能對不同業務的數據分別的進行管理,維護,監控,擴展等。 數據庫往往最容易成為應用系統的瓶頸,而數據庫本身屬于“有狀態”的,相對于Web和應用服務器來講,是比較難實現“橫向擴展”的。 數據庫的連接資源比較寶貴且單機處理能力也有限,在高并發場景下,垂直分庫一定程度上能夠突破IO、連接數及單機硬件資源的瓶頸。

    水平分表

    針對數據量巨大的單張表(比如訂單表),按照某種規則(RANGE,HASH取模等),切分到多張表里面去。 但是這些表還是在同一個庫中,所以庫級別的數據庫操作還是有IO瓶頸。不建議采用。

    水平分庫分表

    將單張表的數據切分到多個服務器上去,每個服務器具有相應的庫與表,只是表中數據集合不同。 水平分庫分表能夠有效的緩解單機和單庫的性能瓶頸和壓力,突破IO、連接數、硬件資源等的瓶頸。

    水平分庫分表切分規則

  • RANGE從
    0到10000一個表,10001到20000一個表;
  • HASH取模
    一個商場系統,一般都是將用戶,訂單作為主表,然后將和它們相關的作為附表,這樣不會造成跨庫事務之類的問題。 取用戶id,然后hash取模,分配到不同的數據庫上。
  • 地理區域
    比如按照華東,華南,華北這樣來區分業務,七牛云應該就是如此。
  • 時間
    按照時間切分,就是將6個月前,甚至一年前的數據切出去放到另外的一張表,因為隨著時間流逝,這些表的數據 被查詢的概率變小,所以沒必要和“熱數據”放在一起,這個也是“冷熱數據分離”。
  • 分庫分表后面臨的問題

    • 事務支持
      分庫分表后,就成了分布式事務了。如果依賴數據庫本身的分布式事務管理功能去執行事務,將付出高昂的性能代價; 如果由應用程序去協助控制,形成程序邏輯上的事務,又會造成編程方面的負擔。
    • 跨庫join

      只要是進行切分,跨節點Join的問題是不可避免的。但是良好的設計和切分卻可以減少此類情況的發生。解決這一問題的普遍做法是分兩次查詢實現。在第一次查詢的結果集中找出關聯數據的id,根據這些id發起第二次請求得到關聯數據。
      分庫分表方案產品

    • 跨節點的count,order by,group by以及聚合函數問題
      這些是一類問題,因為它們都需要基于全部數據集合進行計算。多數的代理都不會自動處理合并工作。解決方案:與解決跨節點join問題的類似,分別在各個節點上得到結果后在應用程序端進行合并。和join不同的是每個結點的查詢可以并行執行,因此很多時候它的速度要比單一大表快很多。但如果結果集很大,對應用程序內存的消耗是一個問題。

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

    • ID問題
    • 一旦數據庫被切分到多個物理結點上,我們將不能再依賴數據庫自身的主鍵生成機制。一方面,某個分區數據庫自生成的ID無法保證在全局上是唯一的;另一方面,應用程序在插入數據之前需要先獲得ID,以便進行SQL路由.
      一些常見的主鍵生成策略

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

    • 跨分片的排序分頁
      般來講,分頁時需要按照指定字段進行排序。當排序字段就是分片字段的時候,我們通過分片規則可以比較容易定位到指定的分片,而當排序字段非分片字段的時候,情況就會變得比較復雜了。為了最終結果的準確性,我們需要在不同的分片節點中將數據進行排序并返回,并將不同分片返回的結果集進行匯總和再次排序,最后再返回給用戶。如下圖所示:

    中間件推薦

    mysql中in 和exists 區別

    mysql中的in語句是把外表和內表作hash 連接,而exists語句是對外表作loop循環,每次loop循環再對內表進行查詢。一直大家都認為exists比in語句的效率要高,這種說法其實是不準確的。這個是要區分環境的。

  • 如果查詢的兩個表大小相當,那么用in和exists差別不大。
  • 如果兩個表中一個較小,一個是大表,則子查詢表大的用exists,子查詢表小的用in。
  • not in 和not exists如果查詢語句使用了not in 那么內外表都進行全表掃描,沒有用到索引;而not extsts的子查詢依然能用到表上的索引。所以無論那個表大,用not exists都比not in要快。
  • 推薦閱讀

    互聯網公司面試必問的Redis題目

    如果有人問你CAP理論是什么,就把這篇文章發給他。

    互聯網公司面試必問的mysql題目(上)

    轉載于:https://www.cnblogs.com/fishlynn/p/9674793.html

    總結

    以上是生活随笔為你收集整理的互联网公司面试必问的mysql题目(下)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。