前段時間應急群有客服反饋,會員管理功能無法按到店時間、到店次數、消費金額 進行排序。經過排查發現是sql執行效率低,並且索引效率低下。遇到這樣的情況我們該如何處理呢?今天我們聊一聊mysql大表查詢優化。
商戶反饋會員管理功能無法按到店時間、到店次數、消費金額 進行排序,一直轉圈圈或轉完無變化,商戶要以此資料來做活動,比較著急,請盡快處理,謝謝。
merchant_member_info
7000w條資料。
member_info
3000w。
不要問我為什麼不分表,改動太大,無能為力。
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...