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