MySQL幾個簡單SQL的優化

2021-09-11 13:32:59 字數 4326 閱讀 3521

最近在做專案的時候,遇到了一些大資料量的操作,有大批量的crud的操作,一開始的實現的方案經過效能測試,發現效能並不是很好,然後開始審查**,對相關可以提公升效能的操作進行了優化,這裡分享給大家。

為模擬執行場景,我這裡建了乙個表,並往裡面新增了300w條資料,表結構如下:

create

table

`tb_big_data` (

`id`

int(11) not

null auto_increment,

`weixin_id`

varchar(64) not

null,

`openid`

varchar(64) not

null,

`status`

int(3) not

null,

`gmt_create` datetime not

null,

`gmt_modified` datetime not

null,

primary key (`id`),

key`weixin_id_gmt_create_openid` (`weixin_id`,`gmt_create`,`openid`)

) engine=innodb auto_increment default

charset=utf8複製**

1.分頁查詢小優化

分頁查詢老生常談,網上各種優化方法都很多,這裡就不提及了,這裡只是分享乙個小技巧:

如何在使用最普通的limit的時候提高效能?

假設我們現在有一條這樣的sql:

select * from

`tb_big_data`

where weixin_id ='gh_266a30a8a1f6'

and gmt_create > '2017-10-10 00:00:00'

order

byid

asclimit

800000, 100;

假如我們現在不能進行其他優化,比如傳入最小id,分表查詢等策略,以及不進行sql預熱,怎麼提高這條sql的速度呢?

其實很簡單我們只需要乙個in操作即可:

select * from

`tb_big_data` t1 where t1.id in (

select tt.id from (

select

idfrom

`tb_big_data` t2 where weixin_id = 'gh_266a30a8a1f6'

and gmt_create > '2017-10-10 00:00:00'

order

by t2.id asc

limit

800100, 100

) as tt);

可以看出只需稍加修改,sql的效率可以提高30%~40%,而且在單條資料記錄越大的情況下效果越好,當然這不是最好的分頁方法,這只是乙個小技巧;

2.減少sql查詢

現在有乙個需求我們現在有乙個使用者的列表(使用者的唯一標識為openid)然後我們需要判斷使用者在當天是否有過相應的記錄;

這是問題其實很簡單,我們首先一想到的操作就是迴圈這個列表乙個乙個判斷,很簡單也很好實現,但是真正測試的時候發現效能卻很差,尤其在資料量大的情況下,倍數級增長,這裡有有網路資料傳輸消耗的時間和sql本身的執行時間;

假設我們現在執行一條以下的sql:

select * from

`tb_big_data`

where weixin_id ='gh_266a30a8a1f6'

and gmt_create > '2017-10-13 00:00:00'

and openid='2n6bvynihm5bzgyx';

現在如果我們執行100次,不敢想象會是什麼情況,慶幸自己發現了這個問題,因為在資料量少的情況下,這個問題表現的並不是那麼嚴重,其實我們稍加改變就能以另一種高效的方式解決這個問題:

select * from

`tb_big_data`

where weixin_id ='gh_266a30a8a1f6'

and gmt_create > '2017-10-13 00:00:00'

and openid in ('2n6bvynihm5bzgyx','1stbvdnl63de2q37','3z8552gxzfi3wy27'...);

發現了沒有,還是用in,而且執行時間幾乎與單條查詢的時間一樣,可見只是單一這一部分處理就可以提公升了很大的效能。

3.特定場景使用sql的批處理

這個跟上一點有乙個相似點,那就是減少sql執行,上面只是查詢而已,而當出現大批量的cud的操作時,執行每條sql,資料庫都會進行事務處理,這將會消耗大量的時間,而且極端情況下會引起大批量sql等待無法執行,導致業務出錯,正是因為這些原因,我們在一些適當的情況下可以使用批處理來解決這個問題。

(1)批量插入

批量插入比較簡單,也比較常用,這裡就給一下基本語法:

insert

into table_name (field1,filed2,...) values (value11,value12,...),(value21,value22,...),...複製**

(2)批量更新

我先舉個簡單的例子,我們現在來根據一些條件來更新資料,具體sql如下:

update

`tb_big_data`

setstatus = 2

where weixin_id ='gh_266a30a8a1f6'

and gmt_create > '2017-10-13 00:00:00'

and openid = '2n6bvynihm5bzgyx';

query ok, 1 row affected (2.28 sec)

rows matched: 1 changed: 1 warnings: 0複製**

很驚訝,我們只是更新了一條記錄,而且更新條件上是有復合索引的,沒想到速度還那麼慢,可以想象如果我們批量更新資料,那得耗時多少;

但是我們看一下另一條sql:

update

`tb_big_data`

setstatus = 1

where

id = 900098;

query ok, 1 row affected (0.00 sec)

rows matched: 1 changed: 1 warnings: 0複製**

上面的id值為之前條件篩選出來的記錄的id,是不是很驚訝,怎麼這條sql執行的時間幾乎不需要什麼時間,所以我們可以利用這個特點和批量查詢簡化批量更新,雖然這種方式不能讓效能到最優,但是也能提公升很大了,我進行了乙個測試,根據相應條件批量更新100條資料:

方式直接批量更新

先批量查主鍵再批量更新

耗時289.12s

1.342s

可以看出這種方式相對對於普通方式來說,效能提公升巨大,具體執行的時候我們也可以將這些sql放在乙個事務提交,減少資料庫事務次數,但只這是一種在**層面上的優化;

另外我們可以利用mysql提供的特殊語法進行批量更新,具體語法為:

#語法

insert into table_name (id,field1,field2,...) values (id1,value11,value12,...),(id1,value11,value12,...),... on duplicate key update field = vaules(field);

#使用例子

insert into `tb_big_data` (id,weixin_id,openid,gmt_create,status) values (1,'gh_266a30a8a1f6','w9q8fmodytjgppsr','2017-10-13 12:00:00',3),(2,'gh_266a30a8a1f6','bu1flmch4i8eegzf','2017-10-13 12:00:00',3) on duplicate key update status = vaules(status);複製**

經過測試這種方式在資料量小的情況下與上述方式效率差不多,但是隨著資料量越來越大,效能也越來越好,缺點的話主要傳輸的資料量很大,不需要更新的字段也需要傳輸。

另外也不推薦大量資料的批量更新,一次不要超過1000條為好。

總的來說,sql優化是一門細心的學問,需要不斷去嘗試,測試,找到最優方式,另外還有一點就是要結合實際情況,綜合考慮選擇合適的方式。

MySQL優化 SQL優化

其實sql語句的優化核心就在避免全表掃瞄上面 對查詢語句優化,避免全表掃瞄 首先應考慮在where及order by涉及的列上建立索引 避免在where子句中對字段進行表示式和函式操作 避免where進行null 等運算導致的全表掃瞄 在group by後面增加order by null就可以防止g...

簡單的sql查詢優化

1 sql中禁止用select from 的寫法 缺點 將會增加服務區io的輸出負擔 2 如果乙個sql比較複雜 則寫完的sql 可以用 在plsql 中用f5 來看起執行計畫,例如sql select from exp booking where booking id like 123123123...

MySQL簡單的優化

最近在看mysql的優化,就做了下筆記,就當給自己一次理論知識上的提公升 通過不同的方式達到提高資料庫效能的目的。優化包括多個方面,比如查詢速度 更新速度 mysql伺服器效能等分析查詢語句 desc 查詢語句 1 select type 查詢語句的型別。表示簡單查詢 primary 表示主查詢 u...