線上千萬級大表排序該如何優化?

2021-10-02 09:23:04 字數 4493 閱讀 2788

前段時間應急群有客服反饋,會員管理功能無法按到店時間、到店次數、消費金額 進行排序。經過排查發現是sql執行效率低,並且索引效率低下。遇到這樣的情況我們該如何處理呢?今天我們聊一聊mysql大表查詢優化。

商戶反饋會員管理功能無法按到店時間、到店次數、消費金額 進行排序,一直轉圈圈或轉完無變化,商戶要以此資料來做活動,比較著急,請盡快處理,謝謝。

merchant_member_info7000w條資料。

member_info3000w。

不要問我為什麼不分表,改動太大,無能為力。

select

mui.id,

mui.merchant_id,

mui.member_id,

date_format(

mui.recently_consume_time,

'%y%m%d%h%i%s'

) recently_consume_time,

ifnull(mui.total_consume_num,

0) total_consume_num,

ifnull(mui.total_consume_amount,

0) total_consume_amount,

(case

when u.nick_name is

null

then

'會員'

when u.nick_name =

''then

'會員'

else

u.nick_name

end)as

'nickname'

, u.***,

u.head_image_url,

u.province,

u.city,

u.country

from

merchant_member_info mui

left

join member_info u on mui.member_id = u.id

where1=

1and mui.merchant_id =

'商戶編號'

order

by mui.recently_consume_time desc

/asc

limit0,

10

經過驗證可以按照「到店時間」進行降序排序,但是無法按照公升序進行排序主要是查詢太慢了。主要原因是:雖然該查詢使用建立了recently_consume_time索引,但是索引效率低下,需要查詢整個索引樹,導致查詢時間過長。

desc 查詢大概需要4s,asc 查詢太慢耗時未知。

因為是對時間建立了索引,最近的時間一定在最後面,公升序查詢,需要查詢更多的資料,才能過濾出相應的結果,所以慢。

目前生產庫的索引

調整索引

需要刪除index_merchant_user_last_time索引,同時將index_merchant_user_merchant_ids單例索引,變為merchant_id,recently_consume_time組合索引。

調整結果(準生產)

調整前後結果對比(準生產)

測試資料

merchant_member_info有902606條記錄。

member_info表有775條記錄。

sql執行效率

優化前

優化後

type由index -> ref

ref由 null -> const

top優化前優化後

到店時間-降序

0.274s

0.003s

到店時間-公升序

11.245s

0.003s

執行的注意事項:

由於表中的資料量太大,請在晚上進行執行,並且需要分開執行。

# 刪除近期消費時間索引

alter table merchant_member_info drop index index_merchant_user_last_time;

# 刪除商戶編號索引

alter table merchant_member_info drop index index_merchant_user_merchant_ids;

# 建立商戶編號和近期消費時間組合索引

alter table merchant_member_info add index idx_merchant_id_recently_time (`merchant_id`,`recently_consume_time`);

經詢問,重建索引花了30分鐘。

上面的sql雖然經過調整索引,雖然能達到較高的執行效率,但是隨著分頁資料的不斷增加,效能會急劇下降。

分頁資料

查詢時間

優化後limit 0,10

0.003s

0.002s

limit 10,10

0.005s

0.002s

limit 100,10

0.009s

0.002s

limit 1000,10

0.044s

0.004s

limit 9000,10

0.247s

0.016s

最終的sql

優化思路:先走覆蓋索引定位到,需要的資料行的主鍵值,然後inner join 回原表,取到其他資料。

select

mui.id,

mui.merchant_id,

mui.member_id,

date_format(

mui.recently_consume_time,

'%y%m%d%h%i%s'

) recently_consume_time,

ifnull(mui.total_consume_num,

0) total_consume_num,

ifnull(mui.total_consume_amount,

0) total_consume_amount,

(case

when u.nick_name is

null

then

'會員'

when u.nick_name =

''then

'會員'

else

u.nick_name

end)as

'nickname'

, u.***,

u.head_image_url,

u.province,

u.city,

u.country

from

merchant_member_info mui

inner

join

(select

idfrom

merchant_member_info

where

merchant_id =

'商戶id'

order

by recently_consume_time desc

limit

9000,10

)as tmp on tmp.id = mui.id

left

join member_info u on mui.member_id = u.id

我是不一樣的科技宅,每天進步一點點,體驗不一樣的生活。我們下期見!

mysql千萬級資料大表該如何優化

1.資料的容量 1 3年內會大概多少條資料,每條資料大概多少位元組 2.資料項 是否有大字段,那些欄位的值是否經常被更新 3.資料查詢sql條件 哪些資料項的列名稱經常出現在where group by order by子句中等 4.資料更新類sql條件 有多少列經常出現update或delete ...

mysql千萬級如何優化?

1 查詢語句上,只寫必要的字段,建好索引,注意一下查詢條件的使用,多表查詢不要用框架 自己寫sql 2 一定要分頁 一些小表也養成習慣,哪怕你在前台設定多一點可選記錄數選項 如,10,50,100,500,1000 區域網環境 不能再多了孩子 3 在一定數量的基礎上,做好表分割槽 4 拆表 5 拆庫...

線上千萬級大表表結構更改方案

最近做專案,遇到乙個問題需要修改線上的某乙個表的表結構,查了下數量,此表資料量在5kw以上。最終修改方案如下 1 需要先備份表,使用如下類似命令 mysqldump u b user h 101.3.20.33 p h password t p3306 database di up subjects...