數(shù)據(jù)庫(kù)
SQL
1、SQL對(duì)大小寫不敏感
2、可以把 SQL 分為兩個(gè)部分:數(shù)據(jù)操作語(yǔ)言 (DML) 和 數(shù)據(jù)定義語(yǔ)言 (DDL)。SQL (結(jié)構(gòu)化查詢語(yǔ)言)是用于執(zhí)行查詢的語(yǔ)法。
2.1 SQL 語(yǔ)言也包含用于更新、插入和刪除記錄的語(yǔ)法。
查詢和更新指令構(gòu)成了 SQL 的 DML 部分:
select - 從數(shù)據(jù)庫(kù)表中獲取數(shù)據(jù)
update - 更新數(shù)據(jù)庫(kù)表中的數(shù)據(jù)
delete - 從數(shù)據(jù)庫(kù)表中刪除數(shù)據(jù)
insert into - 向數(shù)據(jù)庫(kù)表中插入數(shù)據(jù)
2.2 SQL 的數(shù)據(jù)定義語(yǔ)言 (DDL) 部分使我們有能力創(chuàng)建或刪除表格。我們也可以定義索引(鍵),規(guī)定表之間的鏈接,以及施加表間的約束。
SQL 中最重要的 DDL 語(yǔ)句:
create database <數(shù)據(jù)庫(kù)名> - 創(chuàng)建新數(shù)據(jù)庫(kù)
alter database <數(shù)據(jù)庫(kù)名> - 修改數(shù)據(jù)庫(kù)
create table <數(shù)據(jù)庫(kù)名> - 創(chuàng)建新表
alter table <數(shù)據(jù)庫(kù)名> - 變更(改變)數(shù)據(jù)庫(kù)表
drop table <數(shù)據(jù)庫(kù)名> - 刪除表
create index <數(shù)據(jù)庫(kù)名> - 創(chuàng)建索引(搜索鍵)
drop index <數(shù)據(jù)庫(kù)名> - 刪除索引
3、常用SQL語(yǔ)句
3.1 查看現(xiàn)有數(shù)據(jù)庫(kù)/表 show database/tables;
3.2 連接數(shù)據(jù)庫(kù) use <數(shù)據(jù)庫(kù)名>;
3.3 從.sql文件引入SQL語(yǔ)句 source <.sql文件路徑>;
3.4 刪除數(shù)據(jù)庫(kù) drop database <數(shù)據(jù)庫(kù)名>;
3.5 使用如下語(yǔ)句查看表中的列的基本信息:describe <表名>;
9. 在表中插入新紀(jì)錄
INSERT INTO <表名> (<列名1>, <列名2>, <列名3>, …) VALUES (<值1>, <值2>, <值3>, …);
10. 在表中更新記錄
UPDATE <表名> SET <列名1> = <值1>, <列名2> = <值2>, ... WHERE <條件>;
SELECT語(yǔ)句可以從表中選擇數(shù)據(jù):
SELECT <列名1>, <列名2>, … FROM <表名>;
數(shù)據(jù)庫(kù)索引
索引是對(duì)數(shù)據(jù)庫(kù)表中一個(gè)或多個(gè)列的值進(jìn)行排序的數(shù)據(jù)結(jié)構(gòu),以協(xié)助快速查詢、更新數(shù)據(jù)庫(kù)表中數(shù)據(jù)。索引的實(shí)現(xiàn)通常使用B-TREE及其變種。因?yàn)樗饕鎯?chǔ)引擎不會(huì)再去掃描整張表,根節(jié)點(diǎn)保存了子節(jié)點(diǎn)的指針,因此存儲(chǔ)引擎從根節(jié)點(diǎn)開(kāi)始,根據(jù)指針快速尋找數(shù)據(jù),加速了數(shù)據(jù)訪問(wèn)
1). 索引的底層實(shí)現(xiàn)原理和優(yōu)化
在數(shù)據(jù)結(jié)構(gòu)中,最常見(jiàn)的搜索結(jié)構(gòu)就是二叉搜索樹(shù)和AVL樹(shù)(高度平衡的二叉搜索樹(shù),為了提高二叉搜索樹(shù)的效率,減少樹(shù)的平均搜索長(zhǎng)度)。然而,無(wú)論二叉搜索樹(shù)還是AVL樹(shù),當(dāng)數(shù)據(jù)量比較大時(shí),都會(huì)由于樹(shù)的深度過(guò)大而造成I/O讀寫過(guò)于頻繁,進(jìn)而導(dǎo)致查詢效率低下,因此對(duì)于索引而言,多叉樹(shù)結(jié)構(gòu)成為不二選擇。特別地,B-Tree的各種操作能使B樹(shù)保持較低的高度,從而保證高效的查找效率。
2). 索引的優(yōu)點(diǎn)
1、加快數(shù)據(jù)的檢索速度,這也是創(chuàng)建索引的最主要的原因;
2、表和表之間的連接;
3、用分組和排序子句進(jìn)行數(shù)據(jù)檢索時(shí),同樣可以顯著減少查詢中分組和排序的時(shí)間;
4、創(chuàng)建唯一性索引,可以保證數(shù)據(jù)庫(kù)表中每一行數(shù)據(jù)的唯一性;
3). 什么樣的字段適合創(chuàng)建索引?
1、作查詢選擇的字段
2、作表連接的字段
3、出現(xiàn)在order by, group by, distinct 后面的字段
4). 創(chuàng)建索引時(shí)需要注意什么?
1、字段:應(yīng)該指定列為NOT NULL,除非你想存儲(chǔ)NULL。在mysql中,含有空值的列很難進(jìn)行查詢優(yōu)化,因?yàn)樗鼈兪沟盟饕、索引的統(tǒng)計(jì)信息以及比較運(yùn)算更加復(fù)雜。你應(yīng)該用0、一個(gè)特殊的值或者一個(gè)空串代替空值;
2、離散大的字段:(變量各個(gè)取值之間的差異程度)的列放到聯(lián)合索引的前面,可以通過(guò)count()函數(shù)查看字段的差異值,返回值越大說(shuō)明字段的唯一值越多,字段的離散程度高;
3、字段越小越好:數(shù)據(jù)庫(kù)的數(shù)據(jù)存儲(chǔ)以頁(yè)為單位,一頁(yè)存儲(chǔ)的數(shù)據(jù)越多,一次I/O操作獲取的數(shù)據(jù)越大效率越高。
5). 索引的缺點(diǎn)
1、時(shí)間方面:創(chuàng)建索引和維護(hù)索引要耗費(fèi)時(shí)間,具體地,當(dāng)對(duì)表中的數(shù)據(jù)進(jìn)行增加、刪除和修改的時(shí)候,索引也要?jiǎng)討B(tài)的維護(hù),這樣就降低了數(shù)據(jù)的維護(hù)速度;
2、空間方面:索引需要占物理空間。
6). 索引的分類
1、普通索引和唯一性索引:索引列的值的唯一性
2、單個(gè)索引和復(fù)合索引:索引列所包含的列數(shù)
3、聚簇索引與非聚簇索引:聚簇索引按照數(shù)據(jù)的物理存儲(chǔ)進(jìn)行劃分的。
對(duì)于一堆記錄來(lái)說(shuō),使用聚集索引就是對(duì)這堆記錄進(jìn)行堆劃分,即主要描述的是物理上的存儲(chǔ)。正是因?yàn)檫@種劃分方法,導(dǎo)致聚簇索引必須是唯一的。聚集索引可以幫助把很大的范圍,迅速減小范圍。但是查找該記錄,就要從這個(gè)小范圍中Scan了;而非聚集索引是把一個(gè)很大的范圍,轉(zhuǎn)換成一個(gè)小的地圖,然后你需要在這個(gè)小地圖中找你要尋找的信息的位置,最后通過(guò)這個(gè)位置,再去找你所需要的記錄。
7). 主鍵、自增主鍵、主鍵索引與唯一索引概念區(qū)別
1、主鍵:指字段唯一、不為空值的列;
2、主鍵索引:指的就是主鍵,主鍵是索引的一種,是唯一索引的特殊類型。創(chuàng)建主鍵的時(shí)候,數(shù)據(jù)庫(kù)默認(rèn)會(huì)為主鍵創(chuàng)建一個(gè)唯一索引;
3、自增主鍵:字段類型為數(shù)字、自增、并且是主鍵;
4、唯一索引:索引列的值必須唯一,但允許有空值。
主鍵是唯一索引,這樣說(shuō)沒(méi)錯(cuò);但反過(guò)來(lái)說(shuō),唯一索引也是主鍵就錯(cuò)誤了,因?yàn)槲ㄒ凰饕试S空值,主鍵不允許有空值,所以不能說(shuō)唯一索引也是主鍵。
8). 主鍵就是聚集索引嗎?主鍵和索引有什么區(qū)別?
主鍵是一種特殊的唯一性索引,其可以是聚集索引,也可以是非聚集索引。在SQLServer中,主鍵的創(chuàng)建必須依賴于索引,默認(rèn)創(chuàng)建的是聚集索引,但也可以顯式指定為非聚集索引。InnoDB作為MySQL存儲(chǔ)引擎時(shí),默認(rèn)按照主鍵進(jìn)行聚集,如果沒(méi)有定義主鍵,InnoDB會(huì)試著使用唯一的非空索引來(lái)代替。如果沒(méi)有這種索引,InnoDB就會(huì)定義隱藏的主鍵然后在上面進(jìn)行聚集。所以,對(duì)于聚集索引來(lái)說(shuō),你創(chuàng)建主鍵的時(shí)候,自動(dòng)就創(chuàng)建了主鍵的聚集索引。
MySQL如何查看索引情況并優(yōu)化
**索引類型:**mysql中支持 hash索引 和
btree索引 。innodb和myisam只支持
btree索引,而memory和heap存儲(chǔ)引擎可以支持hash和btree索引
**查詢索引方式:**我們可以通過(guò) show status like '%Handler_read%'; 語(yǔ)句查詢當(dāng)前索引使用情況
結(jié)論:
1)如果索引正在工作,則Handler_read_key的值會(huì)很高,這個(gè)值代表一個(gè)行被索引值讀的次數(shù),很低值表名增加索引得到的性能改善不高,因此索引并不經(jīng)常使用
2)如果Handler_read_rnd_next值很高意味著查詢運(yùn)行效率很低,應(yīng)該建立索引補(bǔ)救,這個(gè)值含義是在數(shù)據(jù)文件中讀取下一行的請(qǐng)求數(shù)。如果正在進(jìn)行大量表掃描,Handler_read_rnd_next的數(shù)值將會(huì)很高。說(shuō)明索引不正確或者沒(méi)有利用索引。
優(yōu)化:
1)優(yōu)化insert語(yǔ)句:
1.盡量采用 insert into test values(),(),(),()…
2.如果從不同客戶插入多行,能通過(guò)使用insert delayed語(yǔ)句得到更高的速度,delayed含義是讓insert語(yǔ)句馬上執(zhí)行,其實(shí)數(shù)據(jù)都被放在內(nèi)存隊(duì)列中個(gè),并沒(méi)有真正寫入磁盤,這比每條語(yǔ)句分別插入快的多;low_priority剛好相反,在所有其他用戶對(duì)表的讀寫完后才進(jìn)行插入。
3.將索引文件和數(shù)據(jù)文件分在不同磁盤上存放(利用建表語(yǔ)句)
4.如果進(jìn)行批量插入,可以增加bulk_insert_buffer_size變量值方法來(lái)提高速度,但是只對(duì)MyISAM表使用
5.當(dāng)從一個(gè)文本文件裝載一個(gè)表時(shí),使用load data file,通常比使用insert快20倍
2)優(yōu)化group by語(yǔ)句:
默認(rèn)情況下,mysql會(huì)對(duì)所有g(shù)roup by字段進(jìn)行排序,這與order by類似。如果查詢包括group by但用戶想要避免排序結(jié)果的消耗,則可以指定order by null禁止排序。
3)優(yōu)化order by語(yǔ)句:
某些情況下,mysql可以使用一個(gè)索引滿足order by字句,因而不需要額外的排序。where條件和order by使用相同的索引,并且order by的順序和索引的順序相同,并且order by的字段都是升序或者降序。
4)優(yōu)化嵌套查詢:
mysql4.1開(kāi)始支持子查詢,但是某些情況下,子查詢可以被更有效率的join替代,尤其是join的被動(dòng)表待帶有索引的時(shí)候,原因是mysql不需要再內(nèi)存中創(chuàng)建臨時(shí)表來(lái)完成這個(gè)邏輯上需要兩個(gè)步驟的查詢工作。
數(shù)據(jù)結(jié)構(gòu)
棧和堆的區(qū)別
- 堆和棧的概念存在于數(shù)據(jù)結(jié)構(gòu)中和操作系統(tǒng)內(nèi)存中。
- 在數(shù)據(jù)結(jié)構(gòu)中,
棧中數(shù)據(jù)的存取方式為
先進(jìn)后出。而
堆是一個(gè)
優(yōu)先隊(duì)列,是按優(yōu)先級(jí)來(lái)進(jìn)行排序的,優(yōu)先級(jí)可以按照大小來(lái)規(guī)定。完全二叉樹(shù)是堆的一種實(shí)現(xiàn)方式。
- 在操作系統(tǒng)中,內(nèi)存被分為
棧區(qū)和
堆區(qū)。棧區(qū)內(nèi)存由編譯器自動(dòng)分配釋放,存放函數(shù)的參數(shù)值,局部變量的值等。其操作方式類似于數(shù)據(jù)結(jié)構(gòu)中的棧。堆區(qū)內(nèi)存一般由程序員分配釋放,若程序員不釋放,程序結(jié)束時(shí)可能由垃圾回收機(jī)制回收。
- 在操作系統(tǒng)中,內(nèi)存被分為
樹(shù)的深度優(yōu)先遍歷和廣度優(yōu)先遍歷分別用了什么數(shù)據(jù)結(jié)構(gòu)
樹(shù)的存儲(chǔ)可以分為順序存儲(chǔ)和鏈?zhǔn)酱鎯?chǔ)結(jié)構(gòu),但為了滿足多子樹(shù)的場(chǎng)景,樹(shù)的存儲(chǔ)方式利用了順序存儲(chǔ)和鏈?zhǔn)酱鎯?chǔ)的,其方法有雙親表示法、孩子表示法、孩子兄弟表示法。
1、廣度優(yōu)先遍歷/寬度優(yōu)先搜索(https://www.zhihu.com/question/28549888)
- 英文縮寫為BFS,即Breadth First Search。
- 我們每一次搜索到一個(gè)點(diǎn)的時(shí)候,如果這個(gè)點(diǎn)不符合條件,那么搜索同一層中符合條件的點(diǎn),再把這一層中符合要求的點(diǎn)一一拓展,按照上述形式搜索下去。
- 其過(guò)程檢驗(yàn)來(lái)說(shuō)是對(duì)每一層節(jié)點(diǎn)依次訪問(wèn),訪問(wèn)完一層進(jìn)入下一層,而且每個(gè)節(jié)點(diǎn)只能訪問(wèn)一次。
- 先往隊(duì)列中插入左節(jié)點(diǎn),再插右節(jié)點(diǎn),這樣出隊(duì)就是先左節(jié)點(diǎn)后右節(jié)點(diǎn)了。
- 廣度優(yōu)先遍歷樹(shù),需要用到隊(duì)列(Queue)來(lái)存儲(chǔ)節(jié)點(diǎn)對(duì)象,隊(duì)列的特點(diǎn)就是先進(jìn)先出
2、深度優(yōu)先搜索
- 英文縮寫為DFS,即Depth First Search。
- 我們每一次搜索到一個(gè)點(diǎn)的時(shí)候,如果這個(gè)點(diǎn)不符合條件,那么就return,返回到上一層(就是常說(shuō)的回朔),如果這個(gè)點(diǎn)符合條件,就一直搜索下去,直到?jīng)]有點(diǎn)可以搜索。
- 其過(guò)程簡(jiǎn)要來(lái)說(shuō)是對(duì)每一個(gè)可能的分支路徑深入到不能再深入為止,而且每個(gè)節(jié)點(diǎn)只能訪問(wèn)一次。
- 深度優(yōu)先遍歷各個(gè)節(jié)點(diǎn),需要使用到棧(Stack)這種數(shù)據(jù)結(jié)構(gòu)。
平衡二叉樹(shù) AVL
任一節(jié)點(diǎn)對(duì)應(yīng)的兩棵子樹(shù)的最大高度差為1,也被稱為高度平衡樹(shù)。查找、插入和刪除在平均和最壞情況下的時(shí)間復(fù)雜度都是O(log n)
數(shù)組和鏈表的區(qū)別
數(shù)組的特點(diǎn)
1)在內(nèi)存中,數(shù)組是一塊連續(xù)的區(qū)域。 拿上面的看電影來(lái)說(shuō),這幾個(gè)人在電影院必須坐在一起。
2)數(shù)組需要預(yù)留空間,在使用前要先申請(qǐng)占內(nèi)存的大小,可能會(huì)浪費(fèi)內(nèi)存空間。 比如看電影時(shí),為了保證10個(gè)人能坐在一起,必須提前訂好10個(gè)連續(xù)的位置。這樣的好處就是能保證10個(gè)人可以在一起。但是這樣的缺點(diǎn)是,如果來(lái)的人不夠10個(gè),那么剩下的位置就浪費(fèi)了。如果臨時(shí)有多來(lái)了個(gè)人,那么10個(gè)就不夠用了,這時(shí)可能需要將第11個(gè)位置上的人挪走,或者是他們11個(gè)人重新去找一個(gè)11連坐的位置,效率都很低。如果沒(méi)有找到符合要求的作為,那么就沒(méi)法坐了。
3)插入數(shù)據(jù)和刪除數(shù)據(jù)效率低,插入數(shù)據(jù)時(shí),這個(gè)位置后面的數(shù)據(jù)在內(nèi)存中都要向后移。刪除數(shù)據(jù)時(shí),這個(gè)數(shù)據(jù)后面的數(shù)據(jù)都要往前移動(dòng)。 比如原來(lái)去了5個(gè)人,然后后來(lái)又去了一個(gè)人要坐在第三個(gè)位置上,那么第三個(gè)到第五個(gè)都要往后移動(dòng)一個(gè)位子,將第三個(gè)位置留給新來(lái)的人。 當(dāng)這個(gè)人走了的時(shí)候,因?yàn)樗麄円B在一起的,所以他后面幾個(gè)人要往前移動(dòng)一個(gè)位置,把這個(gè)空位補(bǔ)上。
4)隨機(jī)讀取效率很高。因?yàn)閿?shù)組是連續(xù)的,知道每一個(gè)數(shù)據(jù)的內(nèi)存地址,可以直接找到給地址的數(shù)據(jù)。
5)并且不利于擴(kuò)展,數(shù)組定義的空間不夠時(shí)要重新定義數(shù)組。
鏈表的特點(diǎn)
1)在內(nèi)存中可以存在任何地方,不要求連續(xù)。 在電影院幾個(gè)人可以隨便坐。
2)每一個(gè)數(shù)據(jù)都保存了下一個(gè)數(shù)據(jù)的內(nèi)存地址,通過(guò)這個(gè)地址找到下一個(gè)數(shù)據(jù)。 第一個(gè)人知道第二個(gè)人的座位號(hào),第二個(gè)人知道第三個(gè)人的座位號(hào)……
3)增加數(shù)據(jù)和刪除數(shù)據(jù)很容易。 再來(lái)個(gè)人可以隨便坐,比如來(lái)了個(gè)人要做到第三個(gè)位置,那他只需要把自己的位置告訴第二個(gè)人,然后問(wèn)第二個(gè)人拿到原來(lái)第三個(gè)人的位置就行了。其他人都不用動(dòng)。
3)查找數(shù)據(jù)時(shí)效率低,因?yàn)椴痪哂须S機(jī)訪問(wèn)性,所以訪問(wèn)某個(gè)位置的數(shù)據(jù)都要從第一個(gè)數(shù)據(jù)開(kāi)始訪問(wèn),然后根據(jù)第一個(gè)數(shù)據(jù)保存的下一個(gè)數(shù)據(jù)的地址找到第二個(gè)數(shù)據(jù),以此類推。 要找到第三個(gè)人,必須從第一個(gè)人開(kāi)始問(wèn)起。
4)不指定大小,擴(kuò)展方便。鏈表大小不用定義,數(shù)據(jù)隨意增刪。
各自的優(yōu)缺點(diǎn)
1)數(shù)組的優(yōu)點(diǎn):隨機(jī)訪問(wèn)性強(qiáng);查找速度快
2)數(shù)組的缺點(diǎn):插入和刪除效率低;可能浪費(fèi)內(nèi)存;內(nèi)存空間要求高,必須有足夠的連續(xù)內(nèi)存空間;數(shù)組大小固定,不能動(dòng)態(tài)拓展
1)鏈表的優(yōu)點(diǎn):插入刪除速度快;內(nèi)存利用率高,不會(huì)浪費(fèi)內(nèi)存;大小沒(méi)有固定,拓展很靈活。
2)鏈表的缺點(diǎn);不能隨機(jī)查找,必須從第一個(gè)開(kāi)始遍歷,查找效率低
- | 數(shù)組 | 鏈表 |
---|---|---|
讀取 | O(1) | O(n) |
插入 | O(n) | O(1) |
刪除 | O(n) | O(1) |
動(dòng)態(tài)數(shù)組
數(shù)組按照操作分為增刪改查
增
1)addLast(e):添加的元素是在數(shù)組尾部操作,不需要移動(dòng)其他元素位置,直接添加即可。時(shí)間復(fù)雜度為O(1)。
2)addFirst(e):添加的元素是在頭部操作,插入時(shí)其他元素要依次往后挪。時(shí)間復(fù)雜度為O(n)。
3)add(index,e):根據(jù)索引添加元素,我們并不知道索引具體會(huì)插入在哪個(gè)位置。根據(jù)概率論分析,時(shí)間復(fù)雜度O(n/2) = O(n)。
4)除此之外我們還要考慮resize,當(dāng)數(shù)組進(jìn)行擴(kuò)容時(shí),時(shí)間復(fù)雜度同樣為O(n)。
刪
1) removeLast(e):同增加操作一樣,時(shí)間復(fù)雜度為O(1)。
2)removeFirst(e):同增加操作一樣,時(shí)間復(fù)雜度為O(n)。
3)remove(index,e):同增加操作一樣,時(shí)間復(fù)雜度O(n/2) = O(n)。
4) 一樣也要考慮到擴(kuò)容,時(shí)間復(fù)雜度為O(n)。
改
set(index,e):根據(jù)索引修改元素。當(dāng)知道索引時(shí),可以直接修改元素而不需要對(duì)其他元素進(jìn)行操作。故時(shí)間復(fù)雜度O(1)。
查
1)get(index):通過(guò)索引查詢?cè),直接查找。時(shí)間復(fù)雜度O(1)。
2)contains(e):查看數(shù)組中是否包含該元素。由于不是通過(guò)索引查找,我們需要遍歷數(shù)組,增加了時(shí)間量。時(shí)間復(fù)雜度O(n)。
3)find(e):查看數(shù)組中對(duì)應(yīng)的索引是多少。同contains一樣需要遍歷數(shù)組。時(shí)間復(fù)雜度O(n)。