最近資料庫表資料接近3000萬,查詢效能有點慢
對於mysql資料庫我已經做的:
那為什麼還慢呢?排查發現,雖然分了區,但是有乙個常用的查詢語句,預設並沒有帶時間戳這個字段,分割槽是按時間戳來劃分的,你又不帶時間戳這個字段,那不就得全分割槽檢索了嗎?所以慢啊,分割槽並沒有被有效利用。
就好像網上看到的一些例子,用日期分割槽後,想測試一下效能:
select
count(*
)from mytable;
select
*from mytable where user_id =
34;
效果並不明顯……廢話,你查全部資料,並沒有使用時間戳來篩選,當然是全分割槽檢索了。
我認為表分割槽和程式語言裡中的字典/map
是相似的,按某種規則建立起乙個個存放資料桶,資料按照你給定的規則放進不同的桶裡。依據關鍵字
來確定資料在哪個桶裡,這樣就一下子過濾掉了大部分無效資料。在我的例子裡,時間戳就是這個關鍵字
,如果你不帶這個關鍵字
,那就和未分割槽一樣,還是要在全部分割槽裡查詢。
alter
table mytable
drop
primary
key,
addprimary
key(
`id`
,`device_id`
)partition
by list (device_id %20)
(partition p0 valuesin(
1)engine
=innodb
,partition p1 valuesin(
2)engine
=innodb
,partition p2 valuesin(
3)engine
=innodb
,partition p3 valuesin(
4)engine
=innodb
,partition p4 valuesin(
5)engine
=innodb
,partition p5 valuesin(
6)engine
=innodb
,partition p6 valuesin(
7)engine
=innodb
,partition p7 valuesin(
8)engine
=innodb
,partition p8 valuesin(
9)engine
=innodb
,partition p9 valuesin(
10)engine
=innodb
,partition p10 valuesin(
11)engine
=innodb
,partition p11 valuesin(
12)engine
=innodb
,partition p12 valuesin(
13)engine
=innodb
,partition p13 valuesin(
14)engine
=innodb
,partition p14 valuesin(
15)engine
=innodb
,partition p15 valuesin(
16)engine
=innodb
,partition p16 valuesin(
17)engine
=innodb
,partition p17 valuesin(
18)engine
=innodb
,partition p18 valuesin(
19)engine
=innodb
,partition p19 valuesin(
0)engine
=innodb
);
這樣就可以每次查詢的時候,先按分割槽規則定位到分割槽,只在分割槽中檢索資料了,很快。
merge 分表
在學習過程中,也看到了 merge 分表的方法。
看到有人說 merge 分表比較簡單,應用程式無需改動,只要操作總表即可。
是這樣的,插入是沒問題,但如果查詢仍然操作總表的話,是不會提公升效能的
,因為還是要檢索所有子表內的資料。
所以merge拆表,應該主要是做資料拆分,如果要提公升查詢效能,還是要改程式,直接定位要查詢的子表,才能快。比較適合按日期劃分子表的場景吧。
我想它的優點應該是靈活:
表分割槽表分割槽是真正的對上層應用程式**,不需要改動程式。
查詢時帶上關鍵字
字段,大大縮小查詢範圍。我覺得它的缺點是不靈活:
insert
into mytable_new select
*from mytable where id >=
1and id <
1000000
;
轉移成功後,再把新錶、舊表重新命名一下,就完成了表替換。
rename
table mytable to mytable_old;
rename
table mytable_new to mytable;
可以用 explain 來確認查詢的分割槽
explain
select
*from mytable where device_id =
36;
即使直接使用id進行查詢,加上關鍵字
字段,也能縮小查詢範圍
explain
select
*from mytable where id =
3672
and device_id =
36;
上面如果不帶device_id
,只帶id
查詢,也很快,但仍然是在所有分割槽檢索。帶上device_id
就直接定位到了乙個分割槽,更快。
如果查詢條件中沒帶device_id
,那分割槽就根本沒有被利用到了。下面語句會在所有分割槽中篩選資料
select
*from mytable where class_id =
32and ts between
1593234321
and1594526324
;
所以表分割槽後,上層應用程式查詢時,也要使用關鍵字
字段,使分割槽能夠有效
對於提公升查詢效能:
其實表分割槽就是資料庫按既定規則幫你定位分割槽,縮小了查詢範圍。
而 merge 分表需要你在應用程式層面,按規則定位到子表,縮小查詢範圍。
對資料庫的優化不只是資料庫,還要『優化』使用它的人。資料庫優化好了,某乙個開發人員寫了乙個sql語句,索引全部未命中,分割槽條件欄位未使用……那好了,就是全表掃瞄,對於大表的查詢sql,還是要仔細斟酌,了解表結構、索引設計才能有好的效率,避免全表掃瞄。
mysql 分表,分割槽,分庫相關及merge引擎
為什麼要分表和分割槽?日常開發中我們經常會遇到大表的情況,所謂的大表是指儲存了百萬級乃至千萬級條記錄的表。這樣的表過於龐大,導致資料庫在查詢和插入的時候耗時太長,效能低下,如果涉及聯合查詢的情況,效能會更加糟糕。分表和表分割槽的目的就是減少資料庫的負擔,提高資料庫的效率,通常點來講就是提高表的增刪改...
mysql分表與分割槽
1 首先得確認mysql是否支援分割槽功能,這可以通過命令 show plugins 檢視如果顯示如下,則說明你的mysql版本支援partition 2 innodb一般用於具有事務和外來鍵的場合,它預設將所有的表資料和索引檔案放在乙個名為ibdata1的檔案中,屬於共享表空間。myisam預設每...
Mysql的merge表型別
將多個表在邏輯上當作乙個表 建立後有兩個檔案,frm 表結構定義 mrg union表的名字清單 兩個基本表 create table merge 1 id int 5 not null,name varchar 100 not null,primary key id create table me...