1. 程式人生 > 其它 >單鏈表的構建、遍歷、帶頭結點與不帶頭結點的插入、C實現、考研友好型

單鏈表的構建、遍歷、帶頭結點與不帶頭結點的插入、C實現、考研友好型

1.1 資料庫面經

1.1.1 hivemysql的區別,以及hive的介紹 1.1.2 關係型資料庫和非關係資料庫的理解 1.1.3 聚合函式與非聚合函式的區別

常見聚合函式baimax(最大)、dumin(最小zhi)、sum(求和)、avg(平均dao)等

1.1.4 自增長列

MySQL可以通過AUTO_INCREMENT關鍵字,實現列資料自增。一般用於單表的唯一標識列,常見的有主鍵。每張表最多隻能有一個自增列。

1.1.5 聚集索引和非聚集索引的區別

MySQL中最常見的兩種儲存引擎分別是MyISAM和InnoDB,分別實現了非聚簇索引和聚簇索引。

聚簇索引的解釋是:聚簇索引的順序就是資料的物理儲存順序

非聚簇索引的解釋是:索引順序與資料物理排列順序無關

InnoDB——聚簇索引

聚簇索引的主索引的葉子結點儲存的是鍵值對應的資料本身,輔助索引的葉子結點儲存的是鍵值對應的資料的主鍵鍵值。因此主鍵的值長度越小越好,型別越簡單越好。

聚簇索引的資料和主鍵索引儲存在一起。

聚簇索引的資料是根據主鍵的順序儲存。因此適合按主鍵索引的區間查詢,可以有更少的磁碟I/O,加快查詢速度。但是也是因為這個原因,聚簇索引的插入順序最好按照主鍵單調的順序插入,否則會頻繁的引起頁分裂,嚴重影響效能。

在InnoDB中,如果只需要查詢索引的列,就儘量不要加入其它的列,這樣會提高查詢效率。

1.1.6
MySQL索引的資料結構

https://www.cnblogs.com/nijunyang/p/11406688.html

有一道 MySQL 的面試題,為什麼 MySQL 的索引要使用 B+ 樹而不是其它樹形結構? 比如 B 樹?

現在這個問題的複雜版本可以參考本文:

因為 B樹不管葉子節點還是非葉子節點,都會儲存資料,這樣導致在非葉子節點中能儲存的指標數量變少(有些資料也稱為扇出),指標少的情況下要儲存大量資料,只能增加樹的高度,導致IO 操作變多,查詢效能變低。

1.1.7 資料庫索引,聯合索引是怎麼工作的

https://blog.csdn.net/tongdanping/article/details/79878302

索引是一個排序的列表,在這個列表中儲存著索引的值和包含這個值的資料所在行的實體地址,在資料十分龐大的時候,索引可以大大加快查詢的速度,這是因為使用索引後可以不用掃描全表來定位某行的資料,而是先通過索引表找到該行資料對應的實體地址然後訪問相應的資料。

單列索引:只有位置為查詢條件第一個,其他兩個都沒有用上

劣勢:索引本身也是表,因此會佔用儲存空間;索引表的維護和建立需要時間成本,這個成本隨著資料量增大而增大;構建索引會降低資料表的修改操作(刪除,新增,修改)的效率,因為在修改資料表的同時還需要修改索引表;

常見的索引型別有:主鍵索引、唯一索引、普通索引、全文索引、組合索引

*遵循“最左字首”原則,把最常用作為檢索或排序的列放在最左。 在檢索資料時從聯合索引的最左邊開始匹配。

1.1.7.1 索引的使用策略

1. 什麼時候要使用索引?

主鍵自動建立唯一索引;

經常作為查詢條件在WHERE或者ORDER BY 語句中出現的列要建立索引;

作為排序的列要建立索引;

查詢中與其他表關聯的欄位,外來鍵關係建立索引

高併發條件下傾向組合索引;

用於聚合函式的列可以建立索引,例如使用了max(column_1)或者count(column_1)時的column_1就需要建立索引

2. 什麼時候不要使用索引?

經常增刪改的列不要建立索引;

有大量重複的列不建立索引;

表記錄太少不要建立索引。

3. 索引失效的情況:

在組合索引中不能有列的值為NULL,如果有,那麼這一列對組合索引就是無效的。

<>NOTinnot exists

索引列上做操作(計算,函式,(自動或者手動)型別裝換)

在一個SELECT語句中索引只能使用一次如果在WHERE中使用了那麼在ORDER BY中就不要用了。

多列索引只有查詢條件中使用了這些欄位中第一個欄位時,索引才會被使用。

1.1.8 MySQL索引長度計算

https://juejin.cn/post/6946321350877249550

對於所有的索引欄位, 如果沒有設定not null, 則加1個位元組.

int4個位元組, date3個位元組, char(n)n個字元, varchar(n)n個字元+2個位元組.

對於不同的字符集, 一個字元所佔用的位元組數也不一樣.

latin1編碼一個字元佔用一個位元組

gbk編碼一個字元佔用兩個位元組

utf8編碼一個字元佔用三個位元組

1.1.9 聚合索引

https://juejin.cn/post/6844904073955639304#heading-3

對於聯合索引來說只不過比單值索引多了幾列,而這些索引列全都出現在索引樹上。對於聯合索引,儲存引擎會首先根據第一個索引列排序,如上圖我們可以單看第一個索引列,橫著看,如,1 1 5 12 13....他是單調遞增的;如果第一列相等則再根據第二列排序,依次類推就構成了上圖的索引樹,上圖中的b列都等於1時,則根據c排序,此時c列也相等則按d列排序,如:1 1 4 1 1 5c=4c=5前面,以及13 12 4,13 16 1,13 16 5就可以說明這種情況。

1.1.10 資料庫的隔離級別

SQL 標準定義了四個隔離級別:

l READ-UNCOMMITTED(讀取未提交):

最低的隔離級別,允許讀取尚未提交的資料變更,可能會導致髒讀、幻讀或不可重複讀。

l READ-COMMITTED(讀取已提交):

允許讀取併發事務已經提交的資料,可以阻⽌髒讀,但是幻讀或不可重複讀仍有可能發⽣。

l REPEATABLE-READ(可重複讀):

對同⼀欄位的多次讀取結果都是⼀致的,除⾮資料是被本身事務⾃⼰所修改,可以阻⽌髒讀和不可重複讀,但幻讀仍有可能發⽣。

l SERIALIZABLE(可串⾏化)

最⾼的隔離級別,完全服從ACID的隔離級別。所有的事務依次逐個執⾏,這樣事務之間就完全不可能產⽣⼲擾,也就是說,該級別可以防⽌髒讀、不可重複讀以及幻讀。

MySQL InnoDB 儲存引擎的預設⽀持的隔離級別是 REPEATABLE-READ可重讀。我們可以

通過show variables like '%tx_isolation%'select @@tx_isolation;命令來檢視

隔離級別

髒讀

不可重複讀

幻影讀

READ-UNCOMMITTED

READ-COMMITTED

×

REPEATABLE-READ

×

×

SERIALIZABLE

×

×

×

這⾥需要注意的是:與 SQL 標準不同的地⽅在於 InnoDB 儲存引擎在 REPEATABLE-READ(可重讀)

事務隔離級別下使⽤的是Next-Key Lock 鎖演算法,因此可以避免幻讀的產⽣,這與其他資料庫系統(如 SQL Server)

是不同的。所以說InnoDB 儲存引擎的預設⽀持的隔離級別是 REPEATABLE-READ(可重讀)

已經可以完全保證事務的隔離性要求,即達到了

SQL標準的 SERIALIZABLE(可串⾏化) 隔離級別。因為隔離級別越低,事務請求的鎖越少,所以⼤部分資料庫系統的隔離級別都是 READ-COMMITTED(讀取提交內容) ,但是你要知道的是

InnoDB 儲存引擎預設使⽤ REPEAaTABLE-READ(可重讀) 並不會有任何效能損失。

InnoDB 儲存引擎在 分散式事務 的情況下⼀般會⽤到 SERIALIZABLE(可串⾏化) 隔離級別。

1.1.11 資料庫慢訪問

https://zhuanlan.zhihu.com/p/149338523

1.1.11.1 索引沒起作用的情況

l 使用LIKE關鍵字的查詢語句

在使用LIKE關鍵字進行查詢的查詢語句中,如果匹配字串的第一個字元為“%”,索引不會起作用。只有“%”不在第一個位置索引才會起作用。

l 使用多列索引的查詢語句

MySQL可以為多個欄位建立索引。一個索引最多可以包括16個欄位。對於多列索引,只有查詢條件使用了這些欄位中的第一個欄位時,索引才會被使用。

1.1.11.2 優化資料庫結構

合理的資料庫結構不僅可以使資料庫佔用更小的磁碟空間,而且能夠使查詢速度更快。資料庫結構的設計,需要考慮資料冗餘、查詢和更新的速度、欄位的資料型別是否合理等多方面的內容。

1.1.11.3 將欄位很多的表分解成多個表

對於欄位比較多的表,如果有些欄位的使用頻率很低,可以將這些欄位分離出來形成新表。因為當一個表的資料量很大時,會由於使用頻率低的欄位的存在而變慢。

l 增加中間表

對於需要經常聯合查詢的表,可以建立中間表以提高查詢效率。通過建立中間表,把需要經常聯合查詢的資料插入到中間表中,然後將原來的聯合查詢改為對中間表的查詢,以此來提高查詢效率。

l 分解關聯查詢

將一個大的查詢分解為多個小查詢是很有必要的。
很多高效能的應用都會對關聯查詢進行分解,就是可以對每一個表進行一次單表查詢,然後將查詢結果在應用程式中進行關聯,很多場景下這樣會更高效

1.1.11.4 優化LIMIT分頁

1.1.12 為什麼使用B+樹而不是使用b/ B+Tree對比BTree的優點:

1. 查詢效能更高

因為B樹不管葉子節點還是非葉子節點,都會儲存資料,這樣導致在非葉子節點中能儲存的指標數量變少(有些資料也稱為扇出),指標少的情況下要儲存大量資料,只能增加樹的高度,導致IO操作變多,查詢效能變低;

B+樹是在在葉子節點存放資料,查詢速度快除了樹的層數不高外,葉子節點還維持了一個連結串列,查詢時相當於順序查詢這個連結串列。更重要的是,查詢時對磁碟的IO操作不僅僅查詢了這個資料所在塊的資訊,也將這個塊附近的塊也加進來了,這樣下次查詢時,就不用再次IO,變相加快了查詢速度。

2. 磁碟讀寫代價更低

一般來說B+Tree比BTree更適合實現外存的索引結構,因為儲存引擎的設計專家巧妙的利用了外存(磁碟)的儲存結構,即磁碟的最小儲存單位是扇區(sector),而作業系統的塊(block)通常是整數倍的sector,作業系統以頁(page)為單位管理記憶體,一頁(page)通常預設為4K,資料庫的頁通常設定為作業系統頁的整數倍,因此索引結構的節點被設計為一個頁的大小,然後利用外存的“預讀取”原則,每次讀取的時候,把整個節點的資料讀取到記憶體中,然後在記憶體中查詢,已知記憶體的讀取速度是外存讀取I/O速度的幾百倍,那麼提升查詢速度的關鍵就在於儘可能少的磁碟I/O,那麼可以知道,每個節點中的key個數越多,那麼樹的高度越小,需要I/O的次數越少,因此一般來說B+Tree比BTree更快,因為B+Tree的非葉節點中不儲存data,就可以儲存更多的key。

3. 查詢速度更穩定

由於B+Tree非葉子節點不儲存資料(data),因此所有的資料都要查詢至葉子節點,而葉子節點的高度都是相同的,因此所有資料的查詢速度都是一樣的。

1.1.13 索引的優化

1、 最左字首

索引的最左字首和和B+Tree中的“最左字首原理”有關,舉例來說就是如果設定了組合索引<col1,col2,col3>那麼以下3中情況可以使用索引:col1,<col1,col2>,<col1,col2,col3>,其它的列,比如<col2,col3>, col2,col3等等都是不能使用索引的。

根據最左字首原則,我們一般把排序分組頻率最高的列放在最左邊,以此類推。

2、 帶索引的模糊查詢優化

在上面已經提到,使用LIKE進行模糊查詢的時候,'%aaa%'不會使用索引,也就是索引會失效。如果是這種情況,只能使用全文索引來進行優化(上文有講到)。

3、 使用短索引

對串列進行索引,如果可能應該指定一個字首長度。例如,如果有一個CHAR(255)的 列,如果在前10 個或20 個字元內,多數值是惟一的,那麼就不要對整個列進行索引。短索引不僅可以提高查詢速度而且可以節省磁碟空間和I/O操作。

1.1.14 mysql可以放多少條資料,多少條需要分表

https://www.cnblogs.com/leefreeman/p/8315844.html

假設一行記憶體為1k,可以放2000w條

我們的InnoDB儲存引擎也有自己的最小儲存單元——頁(Page),一個頁的大小是16K。

資料表中的資料都是儲存在頁中的,所以一個頁中能儲存多少行資料呢?假設一行資料的大小是1k,那麼一個頁可以存放16行這樣的資料。

那麼現在我們需要計算出非葉子節點能存放多少指標,其實這也很好算,我們假設主鍵IDbigint型別,長度為8位元組,而指標大小在InnoDB原始碼中設定為6位元組,這樣一共14位元組,我們一個頁中能存放多少這樣的單元,其實就代表有多少指標,即16384/14=1170。那麼可以算出一棵高度為2B+樹,能存放1170*16=18720條這樣的資料記錄。

根據同樣的原理我們可以算出一個高度為3B+樹可以存放:1170*1170*16=21902400條這樣的記錄。所以在InnoDBB+樹高度一般為1-3層,這就能滿足千萬級的資料儲存。在查詢資料時,一次頁的查詢代表一次IO,所以通過主鍵索引查詢通常只需要1-3IO操作即可查到資料。

阿里巴巴《Java 開發手冊》提出單錶行數超過 500 萬行或者單表容量超過 2GB,才推薦進行分庫分表

1.1.15 wherehaving的區別

Where” 是一個約束宣告,使用Where來約束來之資料庫的資料,Where是在結果返回之前起作用的,且Where中不能使用聚合函式。

Having”是一個過濾宣告,是在查詢返回結果集以後對查詢結果進行的過濾操作,在Having中可以使用聚合函式。

1.1.16 mysql主從複製

主要涉及三個執行緒:binlog 執行緒、I/O 執行緒和 SQL 執行緒。

binlog 執行緒 :負責將主伺服器上的資料更改寫入二進位制日誌(Binary log)中。

I/O 執行緒 :負責從主伺服器上讀取二進位制日誌,並寫入從伺服器的中繼日誌(Relay log)。

SQL 執行緒 :負責讀取中繼日誌,解析出主伺服器已經執行的資料更改並在從伺服器中重放(Replay)。

1.1.17 mysql讀寫分離

主伺服器處理寫操作以及實時性要求比較高的讀操作,而從伺服器處理讀操作。

讀寫分離能提高效能的原因在於:

主從伺服器負責各自的讀和寫,極大程度緩解了鎖的爭用;

從伺服器可以使用 MyISAM,提升查詢效能以及節約系統開銷;

增加冗餘,提高可用性。

讀寫分離常用代理方式來實現,代理伺服器接收應用層傳來的讀寫請求,然後決定轉發到哪個伺服器。

1.1.18 多版本併發控制 Mysql MVCC

https://github.com/CyC2018/CS-Notes/blob/master/notes/%E6%95%B0%E6%8D%AE%E5%BA%93%E7%B3%BB%E7%BB%9F%E5%8E%9F%E7%90%86.md

多版本併發控制(Multi-Version Concurrency Control, MVCC)是 MySQL 的 InnoDB 儲存引擎實現隔離級別的一種具體方式,用於實現提交讀和可重複讀這兩種隔離級別。而未提交讀隔離級別總是讀取最新的資料行,要求很低,無需使用 MVCC。可序列化隔離級別需要對所有讀取的行都加鎖,單純使用 MVCC 無法實現。

1.1.19 分散式CAP

分散式系統不可能同時滿足一致性(C:Consistency)、可用性(A:Availability)和分割槽容忍性(P:Partition Tolerance),最多隻能同時滿足其中兩項。

1.1.19.1 一致性

一致性指的是多個數據副本是否能保持一致的特性,在一致性的條件下,系統在執行資料更新操作之後能夠從一致性狀態轉移到另一個一致性狀態。

對系統的一個數據更新成功之後,如果所有使用者都能夠讀取到最新的值,該系統就被認為具有強一致性。

1.1.19.2 可用性

可用性指分散式系統在面對各種異常時可以提供正常服務的能力,可以用系統可用時間佔總時間的比值來衡量,4 9 的可用性表示系統 99.99% 的時間是可用的。

在可用性條件下,要求系統提供的服務一直處於可用的狀態,對於使用者的每一個操作請求總是能夠在有限的時間內返回結果。

1.1.19.3 分割槽容忍性

網路分割槽指分散式系統中的節點被劃分為多個區域,每個區域內部可以通訊,但是區域之間無法通訊。

在分割槽容忍性條件下,分散式系統在遇到任何網路分割槽故障的時候,仍然需要能對外提供一致性和可用性的服務,除非是整個網路環境都發生了故障。

1.1.19.4 權衡

在分散式系統中,分割槽容忍性必不可少,因為需要總是假設網路是不可靠的。因此,CAP 理論實際上是要在可用性和一致性之間做權衡。

可用性和一致性往往是衝突的,很難使它們同時滿足。在多個節點之間進行資料同步時,

1. 為了保證一致性(CP),不能訪問未同步完成的節點,也就失去了部分可用性;

2. 為了保證可用性(AP),允許讀取所有節點的資料,但是資料可能不一致。

1.1.19.5 CAP為什麼只能滿足兩個

https://www.cnblogs.com/fengli9998/p/8866483.html

現在開始分析:

1:滿足C,所有的機器上的資料都是一樣,這樣的情況下會有什麼需求呢?每當一個新資料新增到其中一個伺服器上,這個資料要同步到其它伺服器,這樣的情況下才可以保證C

2:滿足A,這樣的情況下會有什麼需求呢?使用者隨時都在訪問,都能在可控的時間內返回正確的資料

3:滿足P,非常可靠,怎麼能可靠呢?那必須是機器越多越可靠,為啥?我有1億臺伺服器,掛了幾萬臺,完全沒影響嘛。

現在我們對這幾個理論有了一定的瞭解,現在開始分析為啥只能同時滿足兩個

1:滿足C和A,那麼P能不能滿足呢?

滿足C需要所有的伺服器的資料要一樣,也就是說要實現資料的同步,那麼同步要不要時間?肯定是要的,並且機器越多,同步的時間肯定越慢,這裡問題就來了,我們同時也滿足了A,也就是說,我要同步時間短才行。這樣的話,機器就不能太多了,也就是說P是滿足不了的

2:滿足C和P,那麼A能不能滿足呢?

滿足P需要很多伺服器,假設有1000臺伺服器,同時滿足了C,也就是說要保證每臺機器的資料都一樣,那麼同步的時間可就很大,在這種情況下,我們肯定是不能保證使用者隨時訪問每臺伺服器獲取到的資料都是最新的,想要獲取最新的,可以,你就等吧,等全部同步完了,你就可以獲取到了,但是我們的A要求短時間就可以拿到想要的資料啊,這不就是矛盾了,所以說這裡A是滿足不了了

3:滿足A和P,那麼C能不能滿足呢?

滿足P需要很多伺服器,同時也滿足了A,也就是說,我要同步時間短才行,那麼C一致性就不能保證

1.1.20 Mysql的回表

https://www.jianshu.com/p/8991cbca3854

InnoDB聚集索引的葉子節點儲存行記錄,因此, InnoDB必須要有,且只有一個聚集索引:

(1)如果表定義了PK,則PK就是聚集索引;

(2)如果表沒有定義PK,則第一個not NULL unique列是聚集索引;

(3)否則,InnoDB會建立一個隱藏的row-id作為聚集索引;

畫外音:所以PK查詢非常快,直接定位行記錄。

InnoDB普通索引的葉子節點儲存主鍵值。

畫外音:注意,不是儲存行記錄頭指標,MyISAM的索引葉子節點儲存記錄指標。

1.1.20.1 回表索引

如粉紅色路徑,需要掃碼兩遍索引樹:

1)先通過普通索引定位到主鍵值id=5

2)在通過聚集索引定位到行記錄;

這就是所謂的回表查詢,先定位主鍵值,再定位行記錄,它的效能較掃一遍索引樹更低。

1.1.20.2 聚集索引:

一個表中只能有一個,聚集索引的順序與資料真實的物理儲存順序一致。查詢速度賊快,聚集索引的葉子節點上是該行的所有資料 ,資料索引能加快範圍查詢(聚集索引的順序和資料存放的邏輯順序一致)。主鍵!=聚集索引。

1.1.20.3 輔助索引(非聚集索引)

一個表中可以有多個,葉子節點存放的不是一整行資料,而是鍵值,葉子節點的索引行中還包含了一個'書籤',這個書籤就是指向聚簇索引的一個指標,從而在聚簇索引樹中找到一整行資料。

1.1.20.4 聯合索引(複合索引):

就是由多列組成的的索引。遵循最左字首規則。對whereorder bygroup by 都生效。

1、 複合主鍵:指表的主鍵含有一個以上的欄位組成,不使用無業務含義的自增id作為主鍵。

1.1.20.5 覆蓋索引:

指從輔助索引中就能獲取到需要的記錄,而不需要查詢聚簇索引中的記錄。使用覆蓋索引的一個好處是因為輔助索引不包括一條記錄的整行資訊,所以資料量較聚集索引要少,可以減少大量io操作。

1.1.20.6 聚集索引與輔助索引的區別:

葉子節點是否存放的為一整行資料

1.1.20.7 最左字首規則:

假設聯合索引由列(a,b,c)組成,則一下順序滿足最左字首規則:aababcselecewhereorder by group by都可以匹配最左字首。其它情況都不滿足最左字首規則就不會用到聯合索引。

1.1.20.8 DDL更改表的語句,,DML是更改表中資料的語句

1.1.20.9 建立索引的列原則

以下列上適合建立索引:

1) 表的主鍵、外來鍵必須有索引。

2) 經常與其它表進行連線的表,在連線欄位上應該建立索引。

3) 經常出現在WHERE子句中的欄位,特別是大表的欄位,應該建立索引。

4) 索引應該建在選擇性高的欄位上。

5) 索引應該建在小欄位上,對於大的文字欄位甚至超長欄位,不適合建索引。

6) 複合索引的建立需要進行仔細分析。

7) 正確選擇複合索引中的主列欄位,一般是選擇性較好的欄位。

8) 如果單欄位查詢很少甚至沒有,那麼可以建立複合索引;否則考慮單欄位索引。

9) 如果複合索引中包含的欄位經常單獨出現在WHERE子句中,那麼分解為多個單欄位索引。

10) 如果複合索引所包含的欄位超過3個,那麼仔細考慮其必要性,考慮減少複合的欄位。

11) 如果既有單欄位索引,又有這幾個欄位上的複合索引,那麼一般可以刪除複合索引。

12) 頻繁進行DML操作的表,不要建立太多的索引。

13) 刪除無用的索引,避免對執行計劃造成負面影響。



來自為知筆記(Wiz)