DDL(Data Definition Language)資料庫定義語言
CREATE、ALTER、DROP、TRUNCATE、COMMENT、RENAME
DML(Data Manipulation Language)資料操縱語言
SELECT、INSERT、UPDATE、DELETE、MERGE、CALL、EXPLAIN PLAN、LOCK TABLE
左連線、右連線、內連線、全連線
INNER 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
INNER JOIN table_b B
ON A.PK = B.PK;
複製程式碼
LEFT JOIN (左連線)
左連線是左邊表的所有資料都有顯示出來,右邊的表資料只顯示共同有的那部分,沒有對應的部分只能補空顯示,所謂的左邊表其實就是指放在left 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
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)
參考
正規化
關聯式資料庫中的關係是要滿足一定要求的,滿足不同程度要求的為不同正規化。
- 第一正規化(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)
資料庫如果支援事務的操作,那麼就具備以下四個特性:
- 原子性(Atomicity) 事務是資料庫的邏輯工作單位,事務中包括的諸操作要麼全做,要麼全不做。
- 一致性(Consistency) 事務執行的結果必須是使資料庫從一個一致性狀態變到另一個一致性狀態。一致性與原子性是密切相關的。
- 隔離性(Isolation) 一個事務的執行不能被其他事務干擾。
- 持續性/永久性(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)如果在一個程式系統中大量的使用儲存過程,到程式交付使用的時候隨著使用者需求的增加會導致資料結構的變化,接著就是系統的相關問題了,最後如果使用者想維護該系統可以說是很難很難、而且代價是空前的,維護起來更麻煩。
檢視
檢視是從一個或幾個基本表(或檢視)匯出的表。它與基本表不同,是一個虛表。資料庫中只存放檢視的定義,而不存放檢視對應的資料,這些資料仍存放在原來的基本表中。所以一旦基本表中的資料發生變化,從檢視中查詢出的資料也就隨之改變了。從這個意義上講,檢視就像一個視窗,透過它可以看到資料庫中自己感興趣的資料及其變化。 檢視一經定義,就可以和基本表一樣被查詢、被刪除。也可以在一個檢視上再定義新的檢視,但對檢視的更新(增、刪、改)操作則有一定的限制。
檢視的優點
- 查詢簡單化。檢視能簡化使用者的操作
- 資料安全性。檢視使使用者能以多種角度看待同一資料,能夠對機密資料提供安全保護
- 邏輯資料獨立性。檢視對重構資料庫提供了一定程度的邏輯獨立性
檢視的缺點
- 效能。資料庫必須把檢視的查詢轉化成對基本表的查詢,如果這個檢視是由一個複雜的多表查詢所定義,那麼,即使是檢視的一個簡單查詢,資料庫也把它變成一個複雜的結合體,需要花費一定的時間。
- 修改限制。當使用者試圖修改檢視的某些行時,資料庫必須把它轉化為對基本表的某些行的修改。事實上,當從檢視中插入或者刪除時,情況也是這樣。對於簡單檢視來說,這是很方便的,但是,對於比較複雜的檢視,可能是不可修改的,這些檢視有如下特徵: 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)傳輸到從資料庫上,然後將這些日誌重新執行(重做);從而使得從資料庫的資料與主資料庫保持一致。
主從複製的作用
- 主資料庫出現問題,可以切換到從資料庫。
- 可以進行資料庫層面的讀寫分離。
- 可以在從資料庫上進行日常備份。
複製過程
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來獲取資料。
大表資料查詢,怎麼優化
- 優化shema、sql語句+索引;
- 第二加快取,memcached, redis;
- 主從複製,讀寫分離;
- 垂直拆分,根據你模組的耦合度,將一個大的系統分為多個小的系統,也就是分散式系統;
- 水平切分,針對資料量大的表,這一步最麻煩,最能考驗技術水平,要選擇一個合理的sharding key, 為了有好的查詢效率,表結構也要改動,做一定的冗餘,應用也要改,sql中儘量帶sharding key,將資料定位到限定的表上去查,而不是掃描全部的表;
獲取最新資訊,請關注微信公眾號:南強說晚安
秋招求職徵文正在火熱進行中?秋招求職時,寫文就有好禮相送 | 掘金技術徵文 - 掘金