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