互聯網校招面試必備——數據庫 | 掘金技術徵文

DDL(Data Definition Language)數據庫定義語言

CREATE、ALTER、DROP、TRUNCATE、COMMENT、RENAMEmysql

DML(Data Manipulation Language)數據操縱語言

SELECT、INSERT、UPDATE、DELETE、MERGE、CALL、EXPLAIN PLAN、LOCK TABLEweb

左鏈接、右鏈接、內鏈接、全鏈接

INNER JOIN(內鏈接)

內鏈接是一種一一映射關係,就是兩張表都有的才能顯示出來 redis

SELECT  A.PK AS A_PK,A.Value AS A_Value,B.PK AS B_PK,B.Value AS B_Value
FROM table_a A
INNER JOIN table_b B
ON A.PK = B.PK;
複製代碼

LEFT JOIN (左鏈接)

左鏈接是左邊表的全部數據都有顯示出來,右邊的表數據只顯示共同有的那部分,沒有對應的部分只能補空顯示,所謂的左邊表其實就是指放在left join的左邊的表 sql

SELECT  A.PK AS A_PK,A.Value AS A_Value,B.PK AS B_PK,B.Value AS B_Value
FROM table_a A
LEFT JOIN table_b B
ON A.PK = B.PK;
複製代碼

RIGHT JOIN(右鏈接)

右鏈接正好是和左鏈接相反的,這裏的右邊也是相對right join來講的,在這個右邊的表就是右表 數據庫

SELECT  A.PK AS A_PK,A.Value AS A_Value,B.PK AS B_PK,B.Value AS B_Value
FROM table_a A
RIGHT JOIN table_b B
ON A.PK = B.PK;
複製代碼

OUTER JOIN(外鏈接、全鏈接)

查詢出左表和右表全部數據,可是去除兩表的重複數據 後端

由於mysql不支持全鏈接,只能用如下代碼實現效果,含義是左鏈接+右鏈接+去重=全鏈接:

SELECT  A.PK AS A_PK,A.Value AS A_Value,B.PK AS B_PK,B.Value AS B_Value
FROM table_a A
LEFT JOIN  table_b B
ON A.PK = B.PK
 UNION
SELECT  A.PK AS A_PK,A.Value AS A_Value,B.PK AS B_PK,B.Value AS B_Value
FROM table_a A
RIGHT JOIN  table_b B
ON A.PK = B.PK;
複製代碼

交叉鏈接

沒有 WHERE 子句的交叉聯接將產生聯接所涉及的表的笛卡爾積。第一個表的行數乘以第二個表的行數等於笛卡爾積結果集的大小。 用法:A CROSS JOIN B (不要ON)緩存

參考

數據庫左鏈接、右鏈接、內鏈接、全鏈接筆記安全

範式

關係數據庫中的關係是要知足必定要求的,知足不一樣程度要求的爲不一樣範式。bash

  • 第一範式(1NF):符合1NF的關係中的每一個屬性都不可再分。是指數據庫表的每一列都是不可分割的基本數據項,同一列中不能有多個值,即實體中的某個屬性不能有多個值或者不能有重複的屬性。
  • 第二範式(2NF):2NF在1NF的基礎之上,消除了非主屬性對於碼的部分函數依賴。
  • 第三範式(3NF):3NF在2NF的基礎之上,消除了非主屬性對於碼的傳遞函數依賴。

詳細內容參考:知乎——解釋一下關係數據庫的第一第二第三範式?_劉慰服務器

數據庫索引

索引是一種數據結構 。數據庫索引,是數據庫管理系統中一個排序的數據結構,以協助快速查詢、更新數據庫表中數據。索引的實現一般使用B樹及其變種B+樹。

B樹和B+樹的區別

  • 在B樹中,你能夠將鍵和值存放在內部節點和葉子節點;但在B+樹中,內部節點都是鍵,沒有值,葉子節點同時存放鍵和值。
  • B+樹的葉子節點有一條鏈相連,而B樹的葉子節點各自獨立。

使用B樹的好處

B樹能夠在內部節點同時存儲鍵和值,所以,把頻繁訪問的數據放在靠近根節點的地方將會大大提升熱點數據的查詢效率。這種特性使得B樹在特定數據重複屢次查詢的場景中更加高效。

使用B+樹的好處

因爲B+樹的內部節點只存放鍵,不存放值,所以,一次讀取,能夠在內存頁中獲取更多的鍵,有利於更快地縮小查找範圍。 B+樹的葉節點由一條鏈相連,所以,當須要進行一次全數據遍歷的時候,B+樹只須要使用O(logN)時間找到最小的一個節點,而後經過鏈進行O(N)的順序遍歷便可。而B樹則須要對樹的每一層進行遍歷,這會須要更多的內存置換次數,所以也就須要花費更多的時間

數據庫爲何使用B+樹而不是B樹

  • B樹只適合隨機檢索,而B+樹同時支持隨機檢索和順序檢索;
  • B+樹空間利用率更高,可減小I/O次數,磁盤讀寫代價更低。通常來講,索引自己也很大,不可能所有存儲在內存中,所以索引每每以索引文件的形式存儲的磁盤上。這樣的話,索引查找過程當中就要產生磁盤I/O消耗。B+樹的內部結點並無指向關鍵字具體信息的指針,只是做爲索引使用,其內部結點比B樹小,盤塊能容納的結點中關鍵字數量更多,一次性讀入內存中能夠查找的關鍵字也就越多,相對的,IO讀寫次數也就下降了。而IO讀寫次數是影響索引檢索效率的最大因素;
  • B+樹的查詢效率更加穩定。B樹搜索有可能會在非葉子結點結束,越靠近根節點的記錄查找時間越短,只要找到關鍵字便可肯定記錄的存在,其性能等價於在關鍵字全集內作一次二分查找。而在B+樹中,順序檢索比較明顯,隨機檢索時,任何關鍵字的查找都必須走一條從根節點到葉節點的路,全部關鍵字的查找路徑長度相同,致使每個關鍵字的查詢效率至關。
  • B-樹在提升了磁盤IO性能的同時並無解決元素遍歷的效率低下的問題。B+樹的葉子節點使用指針順序鏈接在一塊兒,只要遍歷葉子節點就能夠實現整棵樹的遍歷。並且在數據庫中基於範圍的查詢是很是頻繁的,而B樹不支持這樣的操做。
  • 增刪文件(節點)時,效率更高。由於B+樹的葉子節點包含全部關鍵字,並以有序的鏈表結構存儲,這樣可很好提升增刪效率。

索引類型

  • 主鍵索引: 數據列不容許重複,不容許爲NULL.一個表只能有一個主鍵。
  • 惟一索引: 數據列不容許重複,容許爲NULL值,一個表容許多個列建立惟一索引。
  • 普通索引: 基本的索引類型,沒有惟一性的限制,容許爲NULL值。
  • 彙集索引(Clustered):表中各行的物理順序與鍵值的邏輯(索引)順序相同,每一個表只能有一個
  • 非彙集索引(Non-clustered):非彙集索引指定表的邏輯順序。數據存儲在一個位置,索引存儲在另外一個位置,索引中包含指向數據存儲位置的指針。能夠有多個,小於249個

索引的缺點

  • 時間方面:建立索引和維護索引要耗費時間,具體地,當對錶中的數據進行增長、刪除和修改的時候,索引也要動態的維護,這樣就下降了數據的維護速度;
  • 空間方面:索引須要佔物理空間。

建立索引時須要注意什麼?

  • 非空字段:應該指定列爲NOT NULL,除非你想存儲NULL。在mysql中,含有空值的列很難進行查詢優化,由於它們使得索引、索引的統計信息以及比較運算更加複雜。你應該用0、一個特殊的值或者一個空串代替空值;
  • 取值離散大的字段:(變量各個取值之間的差別程度)的列放到聯合索引的前面,能夠經過count()函數查看字段的差別值,返回值越大說明字段的惟一值越多字段的離散程度高;
  • 索引字段越小越好:數據庫的數據存儲以頁爲單位一頁存儲的數據越多一次IO操做獲取的數據越大效率越高。

最左匹配原則

  • 最左前綴匹配原則,很是重要的原則,mysql會一直向右匹配直到遇到範圍查詢(>、<、between、like)就中止匹配,好比a = 1 and b = 2 and c > 3 and d = 4 若是創建(a,b,c,d)順序的索引,d是用不到索引的,若是創建(a,b,d,c)的索引則均可以用到,a,b,d的順序能夠任意調整。
  • =和in能夠亂序,好比a = 1 and b = 2 and c = 3 創建(a,b,c)索引能夠任意順序,mysql的查詢優化器會幫你優化成索引能夠識別的形式

數據庫事務

事務是一個不可分割的數據庫操做序列,也是數據庫併發控制的基本單位,其執行的結果必須使數據庫從一種一致性狀態變到另外一種一致性狀態。

四大特性(簡稱ACID)

數據庫若是支持事務的操做,那麼就具有如下四個特性:

  1. 原子性(Atomicity) 事務是數據庫的邏輯工做單位,事務中包括的諸操做要麼全作,要麼全不作。
  2. 一致性(Consistency) 事務執行的結果必須是使數據庫從一個一致性狀態變到另外一個一致性狀態。一致性與原子性是密切相關的。
  3. 隔離性(Isolation) 一個事務的執行不能被其餘事務干擾。
  4. 持續性/永久性(Durability) 一個事務一旦提交,它對數據庫中數據的改變就應該是永久性的。

事務的隔離性

數據庫事務的隔離級別有4個,由低到高依次爲Read uncommitted、Read committed、Repeatable read、Serializable,這四個級別能夠逐個解決髒讀、不可重複讀、幻讀這幾類問題。

髒讀 不可重複讀 幻讀
Read uncommitted
Read committed--Sql Server , Oracle ×
Repeatable read--MySQL ×
Serializable × × ×
  • 髒讀(Drity Read):某個事務已更新一份數據,另外一個事務在此時讀取了同一份數據,因爲某些緣由,前一個RollBack了操做,則後一個事務所讀取的數據就會是不正確的。
  • 不可重複讀(Non-repeatable read):在一個事務的兩次查詢之中數據不一致,這多是兩次查詢過程當中間插入了一個事務更新的原有的數據。
  • 幻讀(Phantom Read):在一個事務的兩次查詢中數據筆數不一致,例若有一個事務查詢了幾列(Row)數據,而另外一個事務卻在此時插入了新的幾列數據,先前的事務在接下來的查詢中,就會發現有幾列數據是它先前所沒有的。

隔離級別

Read uncommitted 讀未提交

公司發工資了,領導把5000元打到singo的帳號上,可是該事務並未提交,而singo正好去查看帳戶,發現工資已經到帳,是5000元整,很是高興。但是不幸的是,領導發現發給singo的工資金額不對,是2000元,因而迅速回滾了事務,修改金額後,將事務提交,最後singo實際的工資只有2000元,singo空歡喜一場。

出現上述狀況,即咱們所說的髒讀,兩個併發的事務,「事務A:領導給singo發工資」、「事務B:singo查詢工資帳戶」,事務B讀取了事務A還沒有提交的數據。

當隔離級別設置爲Read uncommitted時,就可能出現髒讀,如何避免髒讀,請看下一個隔離級別。

Read committed 讀提交

singo拿着工資卡去消費,系統讀取到卡里確實有2000元,而此時她的老婆也正好在網上轉帳,把singo工資卡的2000元轉到另外一帳戶,並在singo以前提交了事務,當singo扣款時,系統檢查到singo的工資卡已經沒有錢,扣款失敗,singo十分納悶,明明卡里有錢,爲什麼......

出現上述狀況,即咱們所說的不可重複讀,兩個併發的事務,「事務A:singo消費」、「事務B:singo的老婆網上轉帳」,事務A事先讀取了數據,事務B緊接了更新了數據,並提交了事務,而事務A再次讀取該數據時,數據已經發生了改變。

當隔離級別設置爲Read committed時,避免了髒讀,可是可能會形成不可重複讀。

大多數數據庫的默認級別就是Read committed,好比Sql Server , Oracle。如何解決不可重複讀這一問題,請看下一個隔離級別。

Repeatable read 重複讀

當隔離級別設置爲Repeatable read時,能夠避免不可重複讀。當singo拿着工資卡去消費時,一旦系統開始讀取工資卡信息(即事務開始),singo的老婆就不可能對該記錄進行修改,也就是singo的老婆不能在此時轉帳。

雖然Repeatable read避免了不可重複讀,但還有可能出現幻讀。

singo的老婆工做在銀行部門,她時常經過銀行內部系統查看singo的信用卡消費記錄。有一天,她正在查詢到singo當月信用卡的總消費金額(select sum(amount) from transaction where month = 本月)爲80元,而singo此時正好在外面胡吃海塞後在收銀臺買單,消費1000元,即新增了一條1000元的消費記錄(insert transaction ... ),並提交了事務,隨後singo的老婆將singo當月信用卡消費的明細打印到A4紙上,卻發現消費總額爲1080元,singo的老婆很詫異,覺得出現了幻覺,幻讀就這樣產生了。

注:MySQL的默認隔離級別就是Repeatable read。

Serializable 序列化

Serializable是最高的事務隔離級別,同時代價也花費最高,性能很低,通常不多使用,在該級別下,事務順序執行,不只能夠避免髒讀、不可重複讀,還避免了幻像讀。

總結

Read Uncommitted(讀取未提交內容)

在該隔離級別,全部事務均可以看到其餘未提交事務的執行結果。本隔離級別不多用於實際應用,由於它的性能也不比其餘級別好多少。讀取未提交的數據,也被稱之爲髒讀(Dirty Read)。

Read Committed(讀取提交內容)

這是大多數數據庫系統的默認隔離級別(但不是MySQL默認的)。它知足了隔離的簡單定義:一個事務只能看見已經提交事務所作的改變。這種隔離級別 也支持所謂的不可重複讀(Nonrepeatable Read),由於同一事務的其餘實例在該實例處理其間可能會有新的commit,因此同一select可能返回不一樣結果。

Repeatable Read(可重讀)

這是MySQL的默認事務隔離級別,它確保同一事務的多個實例在併發讀取數據時,會看到一樣的數據行。不過理論上,這會致使另外一個棘手的問題:幻讀 (Phantom Read)。簡單的說,幻讀指當用戶讀取某一範圍的數據行時,另外一個事務又在該範圍內插入了新行,當用戶再讀取該範圍的數據行時,會發現有新的「幻影」 行。InnoDB和Falcon存儲引擎經過多版本併發控制(MVCC,Multiversion Concurrency Control)機制解決了該問題。

Serializable(可串行化)

這是最高的隔離級別,它經過強制事務排序,使之不可能相互衝突,從而解決幻讀問題。簡言之,它是在每一個讀的數據行上加上共享鎖。在這個級別,可能致使大量的超時現象和鎖競爭。

隔離級別與鎖的關係

在Read Uncommitted級別下,讀操做不加S鎖; 在Read Committed級別下,讀操做須要加S鎖,可是在語句執行完之後釋放S鎖; 在Repeatable Read級別下,讀操做須要加S鎖,可是在事務提交以前並不釋放S鎖,也就是必須等待事務執行完畢之後才釋放S鎖。 在Serialize級別下,會在Repeatable Read級別的基礎上,添加一個範圍鎖。保證一個事務內的兩次查詢結果徹底同樣,而不會出現第一次查詢結果是第二次查詢結果的子集。

參考

存儲過程

存儲過程是一個預編譯的SQL語句,優勢是容許模塊化的設計,就是說只須要建立一次,之後在該程序中就能夠調用屢次。若是某次操做須要執行屢次SQL,使用存儲過程比單純SQL語句執行要快。

優勢

1)存儲過程是預編譯過的,執行效率高。 2)存儲過程的代碼直接存放於數據庫中,經過存儲過程名直接調用,減小網絡通信。 3)安全性搞,執行存儲過程須要有必定權限的用戶。 4)存儲過程能夠重複使用,減小數據庫開發人員的工做量。

缺點

1)調試麻煩,可是用 PL/SQL Developer 調試很方便!彌補這個缺點。 2)移植問題,數據庫端代碼固然是與數據庫相關的。可是若是是作工程型項目,基本不存在移植問題。 3)從新編譯問題,由於後端代碼是運行前編譯的,若是帶有引用關係的對象發生改變時,受影響的存儲過程、包將須要從新編譯(不過也能夠設置成運行時刻自動編譯)。 4)若是在一個程序系統中大量的使用存儲過程,到程序交付使用的時候隨着用戶需求的增長會致使數據結構的變化,接着就是系統的相關問題了,最後若是用戶想維護該系統能夠說是很難很難、並且代價是空前的,維護起來更麻煩。

視圖

視圖是從一個或幾個基本表(或視圖)導出的表。它與基本表不一樣,是一個虛表。數據庫中只存放視圖的定義,而不存放視圖對應的數據,這些數據仍存放在原來的基本表中。因此一旦基本表中的數據發生變化,從視圖中查詢出的數據也就隨之改變了。從這個意義上講,視圖就像一個窗口,透過它能夠看到數據庫中本身感興趣的數據及其變化。 視圖一經定義,就能夠和基本表同樣被查詢、被刪除。也能夠在一個視圖上再定義新的視圖,但對視圖的更新(增、刪、改)操做則有必定的限制。

視圖的優勢

  1. 查詢簡單化。視圖能簡化用戶的操做
  2. 數據安全性。視圖使用戶能以多種角度看待同一數據,可以對機密數據提供安全保護
  3. 邏輯數據獨立性。視圖對重構數據庫提供了必定程度的邏輯獨立性

視圖的缺點

  1. 性能。數據庫必須把視圖的查詢轉化成對基本表的查詢,若是這個視圖是由一個複雜的多表查詢所定義,那麼,即便是視圖的一個簡單查詢,數據庫也把它變成一個複雜的結合體,須要花費必定的時間。
  2. 修改限制。當用戶試圖修改視圖的某些行時,數據庫必須把它轉化爲對基本表的某些行的修改。事實上,當從視圖中插入或者刪除時,狀況也是這樣。對於簡單視圖來講,這是很方便的,可是,對於比較複雜的視圖,多是不可修改的,這些視圖有以下特徵:   a.有UNIQUE等集合操做符的視圖。   b.有GROUP BY子句的視圖。   c.有諸如AVG\SUM\MAX等聚合函數的視圖。   d.使用DISTINCT關鍵字的視圖。   e.鏈接表的視圖(其中有些例外)

遊標

遊標是系統爲用戶開設的一個數據緩衝區,存放SQL語句的執行結果,每一個遊標區都有一個名字。用戶能夠經過遊標逐一獲取記錄並賦給主變量,交由主語言進一步處理。

觸發器

觸發器是用戶定義在關係表上的一類由事件驅動的特殊過程。一旦定義,觸發器將被保存在數據庫服務器中。任何用戶對錶的增、刪、改操做均由服務器自動激活相應的觸發器,在關係數據庫管理系統核心層進行集中的完整性控制。觸發器相似於約束,可是比約束更加靈活,能夠實施更爲複雜的檢查和操做,具備更精細和更強大的數據控制能力。

drop、delete與truncate的區別

三者都表示刪除,可是三者有一些差異:

Delete Truncate Drop
類型 屬於DML 屬於DDL 屬於DDL
回滾 可回滾 不可回滾 不可回滾
刪除內容 表結構還在,刪除表的所有或者一部分數據行 表結構還在,刪除表中的全部數據 從數據庫中刪除表,全部的數據行,索引和權限也會被刪除
刪除速度 刪除速度慢,須要逐行刪除 刪除速度快 刪除速度快

所以,在再也不須要一張表的時候,用drop;在想刪除部分數據行時候,用delete;在保留表而刪除全部數據的時候用truncate。

主從複製

將主數據庫中的DDL和DML操做經過二進制日誌(BINLOG)傳輸到從數據庫上,而後將這些日誌從新執行(重作);從而使得從數據庫的數據與主數據庫保持一致。

主從複製的做用

  1. 主數據庫出現問題,能夠切換到從數據庫。
  2. 能夠進行數據庫層面的讀寫分離。
  3. 能夠在從數據庫上進行平常備份。

複製過程

Binary log:主數據庫的二進制日誌 Relay log:從服務器的中繼日誌 第一步:master在每一個事務更新數據完成以前,將該操做記錄串行地寫入到binlog文件中。 第二步:salve開啓一個I/O Thread,該線程在master打開一個普通鏈接,主要工做是binlog dump process。若是讀取的進度已經跟上了master,就進入睡眠狀態並等待master產生新的事件。I/O線程最終的目的是將這些事件寫入到中繼日誌中。 第三步:SQL Thread會讀取中繼日誌,並順序執行該日誌中的SQL事件,從而與主數據庫中的數據保持一致。

Mysql 存儲引擎的區別和比較

MySQL默認的存儲引擎是MyISAM,其餘經常使用的就是InnoDB了。

如何修改數據庫引擎

方式一: 修改配置文件my.ini 將mysql.ini另存爲my.ini,在[mysqld]後面添加default-storage-engine=InnoDB,重啓服務,數據庫默認的引擎修改成InnoDB 方式二:在建表的時候指定

create table mytbl(   
    id int primary key,   
    name varchar(50)   
)type=MyISAM;
複製代碼

方式三:建表後更改

alter table table_name type = InnoDB;
複製代碼
MyISAM InnoDB
存儲結構 每張表被存放在三個文件:frm-表格定義、MYD(MYData)-數據文件、MYI(MYIndex)-索引文件 全部的表都保存在同一個數據文件中(也多是多個文件,或者是獨立的表空間文件),InnoDB表的大小隻受限於操做系統文件的大小,通常爲2GB
存儲空間 MyISAM可被壓縮,存儲空間較小 InnoDB的表須要更多的內存和存儲,它會在主內存中創建其專用的緩衝池用於高速緩衝數據和索引
可移植性、備份及恢復 因爲MyISAM的數據是以文件的形式存儲,因此在跨平臺的數據轉移中會很方便。在備份和恢復時可單獨針對某個表進行操做 免費的方案能夠是拷貝數據文件、備份 binlog,或者用 mysqldump,在數據量達到幾十G的時候就相對痛苦了
事務安全 不支持 每次查詢具備原子性 支持 具備事務(commit)、回滾(rollback)和崩潰修復能力(crash recovery capabilities)的事務安全(transaction-safe (ACID compliant))型表
AUTO_INCREMENT MyISAM表能夠和其餘字段一塊兒創建聯合索引 InnoDB中必須包含只有該字段的索引
SELECT MyISAM更優
INSERT InnoDB更優
UPDATE InnoDB更優
DELETE InnoDB更優 它不會從新創建表,而是一行一行的刪除
COUNT without WHERE MyISAM更優。由於MyISAM保存了表的具體行數 InnoDB沒有保存表的具體行數,須要逐行掃描統計,就很慢了
COUNT with WHERE 同樣 同樣,InnoDB也會鎖表
只支持表鎖 支持表鎖、行鎖 行鎖大幅度提升了多用戶併發操做的新能。可是InnoDB的行鎖,只是在WHERE的主鍵是有效的,非主鍵的WHERE都會鎖全表的
外鍵 不支持 支持
FULLTEXT全文索引 支持 不支持 能夠經過使用Sphinx從InnoDB中得到全文索引,會慢一點

總的來講,MyISAM和InnoDB各有優劣,各有各的使用環境。

可是InnoDB的設計目標是處理大容量數據庫系統,它的CPU利用率是其它基於磁盤的關係數據庫引擎所不能比的。

我以爲使用InnoDB能夠應對更爲複雜的狀況,特別是對併發的處理要比MyISAM高效。同時結合memcache也能夠緩存SELECT來減小SELECT查詢,從而提升總體性能。

  • MyIASM是MySQL默認的引擎,可是它沒有提供對數據庫事務的支持,也不支持行級鎖和外鍵,所以當INSERT(插入)或UPDATE(更新)數據時即寫操做須要鎖定整個表,效率便會低一些。
  • InnoDB是一個事務型的存儲引擎,有行級鎖定和外鍵約束。

參考

mysql 分頁

LIMIT 子句能夠被用於強制 SELECT 語句返回指定的記錄數。LIMIT 接受一個或兩個數字參數。參數必須是一個整數常量。若是給定兩個參數,第一個參數指定第一個返回記錄行的偏移量,第二個參數指定返回記錄行的最大數目。初始記錄行的偏移量是 0(而不是 1)

mysql> SELECT * FROM table LIMIT 5,10; // 檢索記錄行 6-15 
複製代碼

爲了檢索從某一個偏移量到記錄集的結束全部的記錄行,能夠指定第二個參數爲 -1:

mysql> SELECT * FROM table LIMIT 95,-1; // 檢索記錄行 96-last. 
複製代碼

若是隻給定一個參數,它表示返回最大的記錄行數目:

mysql> SELECT * FROM table LIMIT 5; //檢索前 5 個記錄行 
複製代碼

換句話說,LIMIT n 等價於 LIMIT 0,n。

大數據量的分頁優化

查詢從第1000000以後的30條記錄:

SQL代碼1:平均用時6.6秒 SELECT * FROM `cdb_posts` ORDER BY pid LIMIT 1000000 , 30
SQL代碼2:平均用時0.6秒 SELECT * FROM `cdb_posts` WHERE pid >= (SELECT pid FROM  
`cdb_posts` ORDER BY pid LIMIT 1000000 , 1) LIMIT 30
複製代碼

由於要取出全部字段內容,第一種須要跨越大量數據塊並取出,而第二種基本經過直接根據索引字段定位後,才取出相應內容,效率天然大大提高。對limit的優化,不是直接使用limit,而是首先獲取到offset的id,而後直接使用limit size來獲取數據。

大表數據查詢,怎麼優化

  1. 優化shema、sql語句+索引;
  2. 第二加緩存,memcached, redis;
  3. 主從複製,讀寫分離;
  4. 垂直拆分,根據你模塊的耦合度,將一個大的系統分爲多個小的系統,也就是分佈式系統;
  5. 水平切分,針對數據量大的表,這一步最麻煩,最能考驗技術水平,要選擇一個合理的sharding key, 爲了有好的查詢效率,表結構也要改動,作必定的冗餘,應用也要改,sql中儘可能帶sharding key,將數據定位到限定的表上去查,而不是掃描所有的表;

獲取最新資訊,請關注微信公衆號:南強說晚安

秋招求職徵文正在火熱進行中👉秋招求職時,寫文就有好禮相送 | 掘金技術徵文 - 掘金

相關文章
相關標籤/搜索