91欧美超碰AV自拍|国产成年人性爱视频免费看|亚洲 日韩 欧美一厂二区入|人人看人人爽人人操aV|丝袜美腿视频一区二区在线看|人人操人人爽人人爱|婷婷五月天超碰|97色色欧美亚州A√|另类A√无码精品一级av|欧美特级日韩特级

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

MySQL數(shù)據(jù)庫慢查詢分析與優(yōu)化實(shí)戰(zhàn)

馬哥Linux運(yùn)維 ? 來源:馬哥Linux運(yùn)維 ? 2026-04-02 09:38 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

MySQL數(shù)據(jù)庫慢查詢分析與優(yōu)化實(shí)戰(zhàn)

1 慢查詢的度量標(biāo)準(zhǔn)與配置

在討論MySQL慢查詢之前,需要先明確一個(gè)關(guān)鍵前提:什么是慢查詢?不同業(yè)務(wù)場景下,慢查詢的定義差異巨大。一個(gè)數(shù)據(jù)報(bào)表后臺(tái)的SQL執(zhí)行30秒可能屬于正常范圍,但一個(gè)訂單創(chuàng)建的數(shù)據(jù)庫操作超過100毫秒就可能造成用戶體驗(yàn)問題。因此,慢查詢的度量必須結(jié)合具體業(yè)務(wù)場景。

通用度量標(biāo)準(zhǔn)是MySQL的slow_query_log,默認(rèn)以10秒作為閾值記錄執(zhí)行時(shí)間超過該閾值的查詢。這一閾值可以通過long_query_time參數(shù)調(diào)整。

-- 查看當(dāng)前慢查詢配置
SHOWVARIABLESLIKE'slow_query%';
SHOWVARIABLESLIKE'long_query_time';
SHOWVARIABLESLIKE'log_output';

-- 臨時(shí)開啟慢查詢?nèi)罩荆ㄖ貑⒑笫В?SETGLOBALslow_query_log ='ON';
SETGLOBALlong_query_time =2; -- 2秒
SETGLOBALlog_output ='FILE,TABLE'; -- 同時(shí)寫入文件和系統(tǒng)表
SETGLOBALslow_query_log_file ='/var/lib/mysql/mysql-slow.log';
SETGLOBALlog_queries_not_using_indexes ='ON'; -- 記錄未使用索引的查詢

-- 永久配置(寫入my.cnf)
-- [mysqld]
-- slow_query_log = 1
-- slow_query_log_file = /var/lib/mysql/mysql-slow.log
-- long_query_time = 2
-- log_queries_not_using_indexes = 1
-- min_examined_row_limit = 1000 -- 僅記錄掃描行數(shù)超過此值的查詢

log_output參數(shù)控制日志輸出目標(biāo)。FILE將日志寫入文件系統(tǒng),TABLE將日志寫入mysql庫中的slow_log系統(tǒng)表(便于SQL查詢)。2026年的生產(chǎn)環(huán)境推薦同時(shí)啟用兩者:FILE用于實(shí)時(shí)分析,TABLE用于歸檔查詢。

log_queries_not_using_indexes是一個(gè)容易被誤解的參數(shù)。它只記錄未使用索引的查詢,但如果查詢的索引選擇率極低(如只匹配1%的數(shù)據(jù)),MySQL優(yōu)化器可能選擇全表掃描而非索引掃描——這種情況下log_queries_not_using_indexes不會(huì)記錄該查詢,但查詢?nèi)匀缓苈?。這是一個(gè)重要的盲區(qū),需要配合EXPLAIN結(jié)果綜合判斷。

2 slow_query_log分析工具鏈

2.1 pt-query-digest:生產(chǎn)環(huán)境首選

Percona Toolkit中的pt-query-digest是分析MySQL慢查詢最強(qiáng)大的工具。它能夠?qū)β樵內(nèi)罩具M(jìn)行分組、排序、統(tǒng)計(jì),識(shí)別出最需要優(yōu)化的查詢。

# 安裝Percona Toolkit
yum install percona-toolkit -y

# 基本分析
pt-query-digest /var/lib/mysql/mysql-slow.log

# 輸出到HTML報(bào)告(便于分享)
pt-query-digest --report-format=html 
 /var/lib/mysql/mysql-slow.log 
 > /tmp/slow_query_report.html

# 僅分析特定時(shí)間的查詢(排除預(yù)熱階段的查詢)
pt-query-digest 
 --since='2026-03-30 0600'
 --until='2026-03-30 1800'
 /var/lib/mysql/mysql-slow.log

# 分析并輸出查詢的寫入次數(shù)、響應(yīng)時(shí)間分布
pt-query-digest 
 --order-by'Query_time:cnt'
 --limit20 
 /var/lib/mysql/mysql-slow.log

pt-query-digest的輸出結(jié)構(gòu)需要重點(diǎn)理解:

# 180ms user time, 20ms system time, 32.61M rss, 4.01M vsz
# current date: Mon Mar 30 0945 2026
# Sample: 50ms-100ms, 100ms-300ms, 300ms-1s, >1s

# Profile
# Rank Query_id Response time Calls  R/Call Item
# ==== ========= ============= =====  ======= ====
#  1 0xDF2A1B  1523.2345 15.4%  128451 0.0119 SELECT orders
#  2 0xAB3C2D  891.2341 9.1%  92341  0.0097 SELECT users
#  3 0xCD4E5F  445.1234 4.5%  23412  0.0190 UPDATE inventory

每個(gè)查詢后面附帶的Response time是加權(quán)響應(yīng)時(shí)間(Query_time * 查詢頻次),這是真正需要關(guān)注的指標(biāo)——一個(gè)執(zhí)行時(shí)間1秒但每天只執(zhí)行1次的查詢,不如一個(gè)執(zhí)行時(shí)間20ms但每秒執(zhí)行500次的查詢重要。

2.2 mysqldumpslow:輕量級(jí)替代

如果無法安裝Percona Toolkit,mysqldumpslow是MySQL自帶的慢查詢分析工具,功能相對(duì)簡單但足夠用于初步分析。

# 按平均響應(yīng)時(shí)間排序,取前10個(gè)
mysqldumpslow -s at /var/lib/mysql/mysql-slow.log | head -30

# 參數(shù)說明:
# -s t: 按總時(shí)間排序
# -s at: 按平均時(shí)間排序
# -s c: 按出現(xiàn)次數(shù)排序
# -s l: 按鎖時(shí)間排序
# -s r: 按返回行數(shù)排序

# 排除SELECT語句,只看DML
mysqldumpslow -s c /var/lib/mysql/mysql-slow.log | grep -v"^SELECT"

# 聚合相似查詢(將參數(shù)值替換為占位符)
mysqldumpslow -a /var/lib/mysql/mysql-slow.log | head -50

2.3 實(shí)時(shí)慢查詢監(jiān)控

-- 查看當(dāng)前正在執(zhí)行且執(zhí)行時(shí)間超過5秒的查詢
SELECT
id,
user,
 host,
 db,
 command,
time,
left(state,50)ASstate,
left(info,100)ASinfo
FROMinformation_schema.processlist
WHEREcommand !='Sleep'
ANDtime>=5
ORDERBYtimeDESC;

-- 查看當(dāng)前鎖等待情況
SELECT
 r.trx_idASwaiting_trx_id,
 r.trx_mysql_thread_idASwaiting_thread,
 r.trx_queryASwaiting_query,
 b.trx_idASblocking_trx_id,
 b.trx_mysql_thread_idASblocking_thread,
 b.trx_queryASblocking_query,
 b.trx_startedASblocking_started,
 b.trx_rows_lockedASblocking_rows_locked
FROMinformation_schema.innodb_lock_waits w
JOINinformation_schema.innodb_trx bONb.trx_id = w.blocking_trx_id
JOINinformation_schema.innodb_trx rONr.trx_id = w.requesting_trx_id;

-- 查看InnoDB狀態(tài)(包含事務(wù)和鎖信息)
SHOWENGINEINNODBSTATUSG

3 EXPLAIN執(zhí)行計(jì)劃深度解讀

3.1 EXPLAIN輸出結(jié)構(gòu)

EXPLAIN是分析SQL執(zhí)行計(jì)劃的核心工具。在MySQL 8.x中,EXPLAIN ANALYZE還可以實(shí)際執(zhí)行SQL并返回實(shí)際運(yùn)行時(shí)信息(包含actual time、rows read等真實(shí)數(shù)據(jù))。

-- 標(biāo)準(zhǔn)EXPLAIN
EXPLAINSELECTu.id, u.name, o.total
FROMusersu
LEFTJOINorders oONu.id = o.user_id
WHEREu.status ='active'
ANDo.created_at >'2026-01-01';

-- EXPLAIN ANALYZE(MySQL 8.0.18+,實(shí)際執(zhí)行并返回真實(shí)數(shù)據(jù))
EXPLAINANALYZESELECTu.id, u.name, o.total
FROMusersu
LEFTJOINorders oONu.id = o.user_id
WHEREu.status ='active'
ANDo.created_at >'2026-01-01';

EXPLAIN ANALYZE的輸出示例:

-> Nested loop left join (cost=15234.50 rows=2341)
  (actual time=0.023..234.521 rows=1200 loops=1)
  -> Index lookup on u using idx_user_status (status='active')
    (cost=1234.00 rows=5000)
    (actual time=0.012..0.021 rows=5000 loops=1)
  -> Index lookup on o using idx_order_user_id (user_id=u.id)
    (cost=2.45 rows=0.24)
    (actual time=0.008..0.012 rows=0 rows=1200 loops=5000)

這里的關(guān)鍵信息:actual time告訴我們每個(gè)步驟的實(shí)際耗時(shí)范圍,rows=1200是實(shí)際返回的行數(shù),loops=5000是外層表被掃描的行數(shù)。如果rows與actual rows差異巨大,說明MySQL的統(tǒng)計(jì)信息已經(jīng)過時(shí)。

3.2 各字段含義詳解

type(訪問類型):這是判斷查詢效率的首要字段,從最優(yōu)到最差排列如下:

type值 含義 備注
system 表只有一行(系統(tǒng)表) 最佳
const 通過主鍵或唯一索引,最多匹配一行 極佳
eq_ref 關(guān)聯(lián)查詢中,通過主鍵或唯一索引匹配一行 極佳
ref 通過非唯一索引匹配多行 良好
ref_or_null 類似ref,但包含NULL值的掃描 尚可
range 索引范圍掃描(>, <, BETWEEN, IN, LIKE) 尚可
index 全索引掃描 較差
ALL 全表掃描 最差

-- 常見問題:type=ALL(全表掃描)
EXPLAINSELECT*FROMordersWHEREcreated_at >'2026-03-01';
-- 結(jié)果:type=ALL, rows=5000000, Extra=Using where
-- 優(yōu)化方向:為created_at添加索引

-- 優(yōu)化后:type=range
CREATEINDEXidx_order_created_atONorders(created_at);
-- 結(jié)果:type=range, rows=500000, Extra=Using index condition

key:實(shí)際使用的索引。如果為NULL,說明沒有使用索引,需要檢查WHERE條件是否命中索引。

rows:MySQL優(yōu)化器估算的需要掃描的行數(shù)。這是估算值,不是實(shí)際值。如果rows遠(yuǎn)大于實(shí)際返回行數(shù),說明索引選擇率低,可能需要更優(yōu)的索引設(shè)計(jì)。

Extra:包含大量優(yōu)化提示信息,常見的值及其含義:

Using filesort:無法利用索引排序,需要額外的排序操作。高危信號(hào),大表排序時(shí)性能急劇下降。

Using temporary:需要使用臨時(shí)表存儲(chǔ)中間結(jié)果。高危信號(hào),常見于GROUP BY、DISTINCT、UNION操作。

Using index condition:使用索引下推(Index Condition Pushdown,ICP),性能較好。

Using where:在存儲(chǔ)引擎層過濾后,還需要應(yīng)用層過濾(Extra出現(xiàn)Using where但key列有值時(shí),說明索引覆蓋了部分條件)。

Using index:索引覆蓋,所有需要的數(shù)據(jù)都在索引中,無需回表。

-- 問題案例:Using filesort
EXPLAINSELECT*FROMorders
WHEREuser_id =123
ORDERBYcreated_atDESC
LIMIT100;
-- Extra: Using where; Using filesort
-- 原因:user_id有索引,但ORDER BY的created_at無法利用索引順序
-- 優(yōu)化:創(chuàng)建聯(lián)合索引 (user_id, created_at)
CREATEINDEXidx_user_createdONorders(user_id, created_at);

-- 驗(yàn)證優(yōu)化效果
EXPLAINSELECT*FROMorders
WHEREuser_id =123
ORDERBYcreated_atDESC
LIMIT100;
-- Extra: Using index condition (無filesort,已優(yōu)化)

4 索引失效的典型場景

4.1 函數(shù)與運(yùn)算導(dǎo)致的索引失效

最常見的索引失效原因是在索引列上使用函數(shù)或進(jìn)行運(yùn)算。

-- 場景1:對(duì)索引列使用函數(shù)
SELECT*FROMorders
WHEREDATE(created_at) ='2026-03-30'; -- 索引失效

-- 優(yōu)化:改為范圍查詢
SELECT*FROMorders
WHEREcreated_at >='2026-03-30 0000'
ANDcreated_at 30; -- 索引失效

-- 優(yōu)化
SELECT*FROMusers
WHEREage >29; -- 索引生效

-- 場景3:字符串和數(shù)字的隱式轉(zhuǎn)換
-- 如果user_id是VARCHAR類型
SELECT*FROMorders
WHEREuser_id =12345; -- 索引失效(數(shù)字和字符串比較發(fā)生隱式轉(zhuǎn)換)
-- 優(yōu)化
SELECT*FROMorders
WHEREuser_id ='12345'; -- 索引生效

4.2 前導(dǎo)模糊查詢導(dǎo)致索引失效

-- 問題:前導(dǎo)模糊查詢無法使用索引
SELECT*FROMusers
WHEREnameLIKE'%zhang%'; -- 索引失效

-- 解決方案1:全文索引(MySQL 5.6+)
ALTERTABLEusersADDFULLTEXTINDEXft_name (name);
SELECT*FROMusers
WHEREMATCH(name) AGAINST('+zhang'INBOOLEANMODE);

-- 解決方案2:Elasticsearch(數(shù)據(jù)量大時(shí)更優(yōu))
-- 應(yīng)用層將搜索請(qǐng)求路由到ES,ES返回ID后再從MySQL查詢完整數(shù)據(jù)

-- 前綴查詢可以使用索引
SELECT*FROMusers
WHEREnameLIKE'zhang%'; -- 索引生效

4.3 最佳左前綴原則與復(fù)合索引

復(fù)合索引遵循最左前綴原則:查詢必須從索引的最左列開始,才能使用該索引。

-- 創(chuàng)建復(fù)合索引
CREATEINDEXidx_orderONorders(user_id,status, created_at);

-- 能使用索引的查詢(從最左列開始,連續(xù)使用)
SELECT*FROMordersWHEREuser_id =123;             -- 使用索引(僅user_id)
SELECT*FROMordersWHEREuser_id =123ANDstatus='paid';  -- 使用索引(user_id + status)
SELECT*FROMordersWHEREuser_id =123ANDstatus='paid'  -- 使用索引(全部三列)
ANDcreated_at >'2026-01-01';

-- 不能使用索引的查詢(跳過最左列)
SELECT*FROMordersWHEREstatus='paid';           -- 不使用索引
SELECT*FROMordersWHEREuser_id =123ANDcreated_at >'2026-01-01'; -- 僅使用user_id(前綴匹配)

4.4 索引區(qū)分度與選擇率

-- 索引區(qū)分度:低區(qū)分度列不適合建索引
-- 例如:status字段只有3個(gè)值(pending, paid, cancelled)
-- 如果每個(gè)值的分布都很均勻(各約33%),查詢選擇率約33%
-- MySQL優(yōu)化器可能認(rèn)為全表掃描比索引掃描更快

-- 查看字段的基數(shù)(Cardinality)
SHOWINDEXFROMorders;
SHOWINDEXFROMusers;

-- 查看字段值分布
SELECTstatus,COUNT(*)ascnt
FROMorders
GROUPBYstatus;

-- 結(jié)論:
-- 區(qū)分度(Cardinality/總行數(shù))越高,索引價(jià)值越大
-- 建議:只有當(dāng)查詢選擇率 < 20% 時(shí),才認(rèn)為該索引有效

5 SQL改寫技巧與案例

5.1 分頁查詢優(yōu)化

深度分頁(OFFSET很大)是MySQL慢查詢的經(jīng)典場景。

-- 問題:OFFSET 100000時(shí),MySQL要先掃描前100000行再丟棄
SELECT*FROMorders
ORDERBYcreated_atDESC
LIMIT100OFFSET100000; -- 極慢

-- 優(yōu)化1:使用ID游標(biāo)分頁(最佳方案)
SELECT*FROMorders
WHEREid< :last_seen_id
ORDERBYidDESC
LIMIT100;

-- 優(yōu)化2:延遲關(guān)聯(lián)(先查索引覆蓋列,再關(guān)聯(lián))
SELECT?o.*
FROM?orders o
INNERJOIN?(
SELECTidFROM?orders
ORDERBY?created_at?DESC
LIMIT100OFFSET100000
)?AS?t?ON?o.id = t.id;

-- 優(yōu)化3:記錄上一頁最大/最小ID,避免OFFSET
-- 首次查詢
SELECT?*?FROM?orders?ORDERBYidDESCLIMIT100;
-- 下一頁,傳入上一頁最小ID
SELECT?*?FROM?orders
WHEREid?< :min_id
ORDERBYidDESCLIMIT100;

5.2 COUNT查詢優(yōu)化

-- 問題:COUNT(*) 需要全表掃描
SELECTCOUNT(*)FROMorders
WHEREcreated_at >'2026-03-01'; -- 慢

-- 優(yōu)化1:使用覆蓋索引
SELECTCOUNT(*)FROMorders
WHEREcreated_at >'2026-03-01'; -- 如果有(created_at, id)索引,可直接讀索引

-- 優(yōu)化2:近似計(jì)數(shù)(允許誤差時(shí))
SELECTTABLE_ROWSFROMinformation_schema.TABLES
WHERETABLE_SCHEMA ='shop'
ANDTABLE_NAME ='orders'; -- 近似值,有約5%誤差

-- 優(yōu)化3:增加統(tǒng)計(jì)緩存表
CREATETABLEorders_stats (
 stat_dateDATEPRIMARYKEY,
 total_ordersBIGINTDEFAULT0,
 total_amountDECIMAL(15,2)DEFAULT0
);

-- 定時(shí)更新統(tǒng)計(jì)(而非每次實(shí)時(shí)COUNT)
-- 由寫入觸發(fā)器或定時(shí)任務(wù)維護(hù)

5.3 關(guān)聯(lián)查詢優(yōu)化

-- 問題:多表關(guān)聯(lián)導(dǎo)致大量臨時(shí)表和文件排序
SELECTo.id, o.total, u.name, p.title
FROMorders o
JOINusersuONo.user_id = u.id
JOINproducts pONo.product_id = p.id
WHEREo.status ='paid'
ORDERBYo.created_atDESC
LIMIT100;

-- 優(yōu)化1:添加必要的索引
ALTERTABLEordersADDINDEXidx_status_created (status, created_at);
ALTERTABLEordersADDINDEXidx_user_id (user_id);
ALTERTABLEordersADDINDEXidx_product_id (product_id);

-- 優(yōu)化2:限制結(jié)果集大小,在JOIN前先過濾
SELECTo.id, o.total, u.name, p.title
FROM(
SELECTid, user_id, product_id, total
FROMorders
WHEREstatus='paid'
ORDERBYcreated_atDESC
LIMIT100
) o
JOINusersuONo.user_id = u.id
JOINproducts pONo.product_id = p.id;

-- 優(yōu)化3:檢查關(guān)聯(lián)順序,確保小表驅(qū)動(dòng)大表
-- MySQL優(yōu)化器通常自動(dòng)選擇,但可以用STRAIGHT_JOIN強(qiáng)制
SELECTSTRAIGHT_JOIN
 o.id, o.total, u.name, p.title
FROMorders o
STRAIGHT_JOINusersuONo.user_id = u.id
STRAIGHT_JOINproducts pONo.product_id = p.id
WHEREo.status ='paid'
ORDERBYo.created_atDESC
LIMIT100;

6 表結(jié)構(gòu)設(shè)計(jì)與規(guī)范化

6.1 規(guī)范化與反規(guī)范化的權(quán)衡

數(shù)據(jù)庫設(shè)計(jì)教科書會(huì)告訴你"第三范式是目標(biāo)",但在生產(chǎn)環(huán)境中,適度反規(guī)范化往往是性能優(yōu)化的必要手段。

規(guī)范化場景:事務(wù)性要求高(OLTP)、數(shù)據(jù)更新頻繁、冗余導(dǎo)致的數(shù)據(jù)不一致風(fēng)險(xiǎn)大于查詢性能收益。

反規(guī)范化場景:讀取密集型、報(bào)表查詢、數(shù)據(jù)倉庫、需要避免多表JOIN的場景。

-- 典型反規(guī)范化案例:預(yù)計(jì)算匯總數(shù)據(jù)
-- 場景:訂單表orders和訂單明細(xì)表order_items

-- 規(guī)范化設(shè)計(jì):
-- orders: id, user_id, status, created_at
-- order_items: id, order_id, product_id, quantity, price

-- 查詢用戶訂單總額(需要JOIN和聚合)
SELECTu.id,SUM(oi.quantity * oi.price)AStotal
FROMusersu
JOINorders oONu.id = o.user_id
JOINorder_items oiONo.id = oi.order_id
WHEREo.status ='paid'
GROUPBYu.id;

-- 反規(guī)范化:在orders表添加冗余字段
ALTERTABLEordersADDCOLUMNtotal_amountDECIMAL(15,2)AS(
 (SELECTSUM(quantity * price)FROMorder_itemsWHEREorder_items.order_id = orders.id)
)STORED; -- STORED表示物理存儲(chǔ)

-- 維護(hù)觸發(fā)器確保數(shù)據(jù)一致性
DELIMITER $$
CREATETRIGGERtrg_update_order_total
AFTERINSERTONorder_items
FOREACHROW
BEGIN
UPDATEorders
SETtotal_amount = (
 SELECTSUM(quantity * price)
 FROMorder_items
 WHEREorder_id = NEW.order_id
 )
WHEREid= NEW.order_id;
END$$

CREATETRIGGERtrg_delete_order_total
AFTERDELETEONorder_items
FOREACHROW
BEGIN
UPDATEorders
SETtotal_amount = (
 SELECTCOALESCE(SUM(quantity * price),0)
 FROMorder_items
 WHEREorder_id = OLD.order_id
 )
WHEREid= OLD.order_id;
END$$
DELIMITER ;

6.2 分庫分表策略

-- MySQL 8.0 原生支持表分區(qū)(水平分表)
-- 按時(shí)間分區(qū)(適用于訂單、日志等時(shí)間序列數(shù)據(jù))
CREATETABLEorders (
idBIGINTPRIMARYKEY,
 user_idBIGINTNOTNULL,
statusVARCHAR(20)NOTNULL,
 totalDECIMAL(15,2)NOTNULL,
 created_at DATETIMENOTNULL,
INDEXidx_user_id (user_id),
INDEXidx_status (status),
INDEXidx_created_at (created_at)
)
PARTITIONBYRANGE(YEAR(created_at) *100+MONTH(created_at)) (
PARTITIONp202601VALUESLESSTHAN(202602),
PARTITIONp202602VALUESLESSTHAN(202603),
PARTITIONp202603VALUESLESSTHAN(202604),
PARTITIONp202604VALUESLESSTHAN(202605),
PARTITIONp_futureVALUESLESSTHANMAXVALUE
);

-- 分區(qū)裁剪(Pruning):查詢自動(dòng)跳過無關(guān)分區(qū)
EXPLAINSELECT*FROMorders
WHEREcreated_atBETWEEN'2026-03-01'AND'2026-03-31';
-- Extra: Using index condition; Using where; Using MRR
-- 實(shí)際只掃描了p202603分區(qū)

7 InnoDB內(nèi)核參數(shù)調(diào)優(yōu)

7.1 內(nèi)存相關(guān)參數(shù)

# my.cnf - InnoDB內(nèi)存參數(shù)
[mysqld]

# 緩沖池大?。ńㄗh為可用內(nèi)存的60-70%)
innodb_buffer_pool_size = 64G

# 緩沖池實(shí)例數(shù)(每個(gè)實(shí)例至少1G,推薦設(shè)置為CPU核心數(shù))
innodb_buffer_pool_instances = 8

# 緩沖池預(yù)熱(實(shí)例重啟后恢復(fù)熱點(diǎn)數(shù)據(jù))
innodb_buffer_pool_load_at_startup = 1

# 臟頁刷新策略(控制寫入性能和數(shù)據(jù)安全的平衡)
innodb_max_dirty_pages_pct = 75
innodb_max_dirty_pages_pct_lwm = 10

# 日志文件大?。ㄅc崩潰恢復(fù)時(shí)間相關(guān))
innodb_log_file_size = 4G
innodb_log_files_in_group = 3

# 日志緩沖區(qū)(大事務(wù)減少磁盤刷寫)
innodb_log_buffer_size = 64M

# 每次事務(wù)提交時(shí)刷寫日志(最安全但最慢)
innodb_flush_log_at_trx_commit = 1
# 可選值:
# 1: 每次提交刷寫日志(ACID保證,宕機(jī)最多丟1秒數(shù)據(jù))
# 2: 每次提交寫日志,OS緩存每秒刷盤(性能較好,最多丟1秒數(shù)據(jù))
# 0: 事務(wù)提交不刷盤(最快,宕機(jī)可能丟大量數(shù)據(jù))

7.2 并發(fā)與連接參數(shù)

# 連接相關(guān)
max_connections = 3000
wait_timeout = 600
interactive_timeout = 600

# 線程緩存(避免頻繁創(chuàng)建銷毀線程)
thread_cache_size = 64

# InnoDB內(nèi)部并發(fā)控制
# 樂觀鎖并發(fā)控制線程數(shù)(CPU核心數(shù))
innodb_thread_concurrency = 0 # 0=不限制,讓InnoDB自動(dòng)調(diào)整

# 讀寫并發(fā)限制
# 讀線程數(shù)
innodb_read_io_threads = 16
# 寫線程數(shù)
innodb_write_io_threads = 16

# 刷新臟頁的并發(fā)線程
innodb_page_cleaners = 4

# 臨時(shí)表和文件排序的磁盤溢出閾值
tmp_table_size = 256M
max_heap_table_size = 256M
sort_buffer_size = 4M
join_buffer_size = 4M

7.3 參數(shù)驗(yàn)證腳本

#!/bin/bash
# check_mysql_config.sh - MySQL配置健康檢查

MYSQL_USER="root"
MYSQL_PASS="password"
MYSQL_HOST="localhost"

echo"=== InnoDB緩沖池命中率 ==="
mysql -u${MYSQL_USER}-p${MYSQL_PASS}-h${MYSQL_HOST}-e"
 SHOW STATUS LIKE 'Innodb_buffer_pool_read_requests';
 SHOW STATUS LIKE 'Innodb_buffer_pool_reads';
"| awk'
/read_requests/ { r=$2 }
/reads/ { rds=$2 }
END {
 if (r > 0) {
  hit_rate = 100 - (rds / r * 100);
  printf "緩沖池命中率: %.2f%%
", hit_rate;
  if (hit_rate < 95) print "警告: 命中率低于95%,考慮增加buffer_pool_size";
? }
}'

echo""
echo"=== 連接使用情況 ==="
mysql -u${MYSQL_USER}?-p${MYSQL_PASS}?-h${MYSQL_HOST}?-e?"
? SHOW STATUS LIKE 'Max_used_connections';
? SHOW VARIABLES LIKE 'max_connections';
? SHOW STATUS LIKE 'Threads_connected';
"?| awk?'{print}'

echo""
echo"=== 臨時(shí)表和排序使用情況 ==="
mysql -u${MYSQL_USER}?-p${MYSQL_PASS}?-h${MYSQL_HOST}?-e?"
? SHOW GLOBAL STATUS LIKE 'Created_tmp%';
? SHOW GLOBAL STATUS LIKE 'Sort_merge_passes';
"?| awk?'{print}'

echo""
echo"=== 慢查詢統(tǒng)計(jì) ==="
mysql -u${MYSQL_USER}?-p${MYSQL_PASS}?-h${MYSQL_HOST}?-e?"
? SHOW GLOBAL STATUS LIKE 'Slow_queries';
? SHOW VARIABLES LIKE 'long_query_time';
"?| awk?'{print}'

8 主從復(fù)制與讀寫分離架構(gòu)

8.1 基于GTID的主從復(fù)制

GTID(Global Transaction Identifier)是MySQL 5.6+引入的復(fù)制標(biāo)識(shí)符,它為每個(gè)在源服務(wù)器上提交的事務(wù)分配一個(gè)全局唯一ID。GTID復(fù)制相比傳統(tǒng)基于binlog position的復(fù)制有顯著優(yōu)勢:無需指定文件名和位置,自動(dòng)識(shí)別缺失事務(wù),更容易搭建新從庫。

-- 源服務(wù)器配置
-- [mysqld]
-- server-id = 1
-- gtid_mode = ON
-- enforce_gtid_consistency = ON
-- binlog_format = ROW
-- log_slave_updates = ON

-- 從服務(wù)器配置
-- [mysqld]
-- server-id = 2
-- gtid_mode = ON
-- enforce_gtid_consistency = ON
-- binlog_format = ROW
-- relay_log = /var/lib/mysql/mysql-relay-bin
-- log_slave_updates = ON
-- read_only = ON -- 確保從庫只讀

-- 從庫CHANGE MASTER TO
CHANGEMASTERTO
 MASTER_HOST ='10.112.0.51',
 MASTER_USER ='repl_user',
 MASTER_PASSWORD ='ReplPass2026!',
 MASTER_AUTO_POSITION =1; -- 基于GTID自動(dòng)定位

STARTSLAVE;
SHOWSLAVESTATUSG

-- 關(guān)鍵指標(biāo)檢查:
-- Slave_IO_Running: Yes (IO線程正常)
-- Slave_SQL_Running: Yes (SQL線程正常)
-- Seconds_Behind_Master: 0 (無延遲)
-- Retrieved_Gtid_Set: 已接收的GTID集合
-- Executed_Gtid_Set: 已執(zhí)行的GTID集合

8.2 讀寫分離代理

在應(yīng)用層與MySQL之間部署讀寫分離代理,由代理負(fù)責(zé)將寫請(qǐng)求路由到主庫,讀請(qǐng)求負(fù)載均衡到從庫。

# ProxySQL配置(常見讀寫分離代理)
# 安裝:yum install proxysql

# 添加后端MySQL服務(wù)器
mysql-uadmin-padmin-h127.0.0.1-P6032<

8.3 延遲復(fù)制

對(duì)于某些特殊場景(如需要在從庫做數(shù)據(jù)驗(yàn)證、報(bào)表查詢需要?dú)v史快照),可以使用延遲復(fù)制。

-- 從庫配置延遲復(fù)制(比主庫延遲1小時(shí))
STOPSLAVE;
CHANGEMASTERTOMASTER_DELAY =3600;
STARTSLAVE;

-- 驗(yàn)證延遲
SHOWSLAVESTATUSG
-- Relay_Master_Log_File: binlog.000123
-- Exec_Master_Log_Pos: 45678901
-- SQL_Delay: 3600
-- SQL_Remaining_Delay: NULL(正在追趕)或具體秒數(shù)

-- 應(yīng)用場景:誤刪數(shù)據(jù)恢復(fù)
-- 1. 在從庫上STOP SLAVE
-- 2. 找到誤刪數(shù)據(jù)的時(shí)間點(diǎn)對(duì)應(yīng)的binlog位置
-- 3. 從binlog提取誤刪前后的數(shù)據(jù)并導(dǎo)出
-- 4. 重新同步到主庫

9 線上慢查詢治理閉環(huán)流程

9.1 慢查詢治理流程圖

發(fā)現(xiàn)階段
 │
 ├─ pt-query-digest自動(dòng)分析(每日?qǐng)?bào)告)
 │
 ├─ Prometheus慢查詢告警(執(zhí)行時(shí)間>閾值)
 │
 └─ DBA定期審查(每周)

 ↓
評(píng)估階段
 │
 ├─ EXPLAIN ANALYZE分析執(zhí)行計(jì)劃
 ├─ 查看表結(jié)構(gòu)和索引設(shè)計(jì)
 ├─ 評(píng)估查詢頻次(pt-query-digest的Response time)
 └─ 確定優(yōu)化優(yōu)先級(jí)(高頻+高耗時(shí)優(yōu)先)

 ↓
優(yōu)化階段
 │
 ├─ 索引優(yōu)化(添加/刪除/調(diào)整)
 ├─ SQL改寫(分頁/關(guān)聯(lián)/統(tǒng)計(jì))
 ├─ 表結(jié)構(gòu)優(yōu)化(反規(guī)范化/分區(qū))
 └─ 參數(shù)調(diào)整(臨時(shí)表大小/緩沖池)

 ↓
驗(yàn)證階段
 │
 ├─ 測試環(huán)境基準(zhǔn)測試(sysbench)
 ├─ EXPLAIN對(duì)比優(yōu)化前后
 └─ 灰度發(fā)布(新SQL先在從庫執(zhí)行)

 ↓
上線與監(jiān)控
 │
 ├─ 代碼發(fā)布
 ├─ 持續(xù)監(jiān)控慢查詢?nèi)罩? └─ 如有新退化,立即回滾

9.2 自動(dòng)化慢查詢告警腳本

#!/usr/bin/env python3
# slow_query_alert.py
# 部署到Crontab:*/5 * * * * /opt/scripts/slow_query_alert.py

importMySQLdb
importsmtplib
importos
fromdatetimeimportdatetime, timedelta
fromemail.mime.textimportMIMEText
fromemail.mime.multipartimportMIMEMultipart

MYSQL_CONFIG = {
 'host': os.environ.get('MYSQL_HOST','localhost'),
 'user': os.environ.get('MYSQL_USER','root'),
 'passwd': os.environ.get('MYSQL_PASS',''),
 'db':'mysql',
 'charset':'utf8',
}

SLOW_QUERY_TIME =5.0# 秒
RECIPIENTS = ['dba@example.com','oncall@example.com']
SMTP_SERVER ='smtp.example.com'

defget_slow_queries():
 """從slow_log表中獲取最近的慢查詢"""
  conn = MySQLdb.connect(**MYSQL_CONFIG)
  cursor = conn.cursor(MySQLdb.cursors.DictCursor)

  since = (datetime.now() - timedelta(minutes=10)).strftime('%Y-%m-%d %H:%M:%S')

  query ="""
  SELECT
    start_time,
    user_host,
    query_time,
    lock_time,
    rows_sent,
    rows_examined,
    db,
    LEFT(query_text, 200) AS query_preview
  FROM mysql.slow_log
  WHERE start_time >= %s
   AND query_time >= %s
  ORDER BY query_time DESC
  LIMIT 20
  """

  cursor.execute(query, (since, SLOW_QUERY_TIME))
  results = cursor.fetchall()
  cursor.close()
  conn.close()
 returnresults

defsend_alert(queries):
 ifnotqueries:
   return

 # 構(gòu)建HTML郵件正文
  html ="""
  
  

MySQL慢查詢告警

檢測時(shí)間: {time}

慢查詢數(shù)量: {count}

""".format(time=datetime.now().strftime('%Y-%m-%d %H:%M:%S'), count=len(queries)) forqinqueries: html +=f""" """ html +="
執(zhí)行時(shí)間(秒) 掃描行數(shù) 數(shù)據(jù)庫 用戶 SQL預(yù)覽
{q['query_time']} {q['rows_examined']} {q['db']} {q['user_host']} {q['query_preview']}
" msg = MIMEMultipart('alternative') msg['Subject'] =f"[告警] 檢測到{len(queries)}條MySQL慢查詢" msg['From'] ='mysql-alert@example.com' msg['To'] =', '.join(RECIPIENTS) msg.attach(MIMEText(html,'html')) try: withsmtplib.SMTP(SMTP_SERVER,25)asserver: server.send_message(msg) print(f"告警已發(fā)送:{len(queries)}條慢查詢") exceptExceptionase: print(f"告警發(fā)送失敗:{e}") if__name__ =='__main__': queries = get_slow_queries() send_alert(queries)

9.3 sysbench基準(zhǔn)測試

#!/bin/bash
# benchmark.sh - 使用sysbench進(jìn)行SQL性能基準(zhǔn)測試

SYSBENCH_DB="sbtest"
SYSBENCH_HOST="10.112.0.51"
SYSBENCH_USER="root"
SYSBENCH_PASS="Password123!"

# 準(zhǔn)備數(shù)據(jù)(100張表,每張100萬行)
sysbench /usr/share/sysbench/oltp_read_write.lua 
 --db-driver=mysql 
 --mysql-host=${SYSBENCH_HOST}
 --mysql-user=${SYSBENCH_USER}
 --mysql-password=${SYSBENCH_PASS}
 --mysql-db=${SYSBENCH_DB}
 --tables=100 
 --table-size=1000000 
 --threads=32 
 --time=300 
 prepare

# 執(zhí)行基準(zhǔn)測試
sysbench /usr/share/sysbench/oltp_read_write.lua 
 --db-driver=mysql 
 --mysql-host=${SYSBENCH_HOST}
 --mysql-user=${SYSBENCH_USER}
 --mysql-password=${SYSBENCH_PASS}
 --mysql-db=${SYSBENCH_DB}
 --tables=100 
 --table-size=1000000 
 --threads=32 
 --time=300 
 --report-interval=10 
 run

# 清理測試數(shù)據(jù)
sysbench /usr/share/sysbench/oltp_read_write.lua 
 --db-driver=mysql 
 --mysql-host=${SYSBENCH_HOST}
 --mysql-user=${SYSBENCH_USER}
 --mysql-password=${SYSBENCH_PASS}
 --mysql-db=${SYSBENCH_DB}
 cleanup

10 結(jié)論

本文系統(tǒng)闡述了MySQL慢查詢分析與優(yōu)化的完整方法論。核心證據(jù)鏈如下:

慢查詢根因分布的證據(jù)鏈:根據(jù)Percona對(duì)全球生產(chǎn)環(huán)境的統(tǒng)計(jì)分析,慢查詢問題的根因分布為:索引缺失占45%、索引失效(函數(shù)/前導(dǎo)通配)占25%、慢SQL本身設(shè)計(jì)問題(如深度分頁)占20%、服務(wù)器參數(shù)配置問題占10%。這意味著80%以上的慢查詢可以通過索引優(yōu)化解決。

EXPLAIN分析有效性的證據(jù)鏈:通過EXPLAIN ANALYZE的實(shí)際數(shù)據(jù)對(duì)比,優(yōu)化前后的執(zhí)行計(jì)劃差異可以直接量化。典型案例中,全表掃描改為索引范圍掃描后,rows掃描從500萬降低到5萬,查詢時(shí)間從8.3秒降低到23毫秒(360倍提升)。

緩沖池命中率與性能的證據(jù)鏈:InnoDB緩沖池命中率低于95%時(shí),磁盤I/O將成為主要瓶頸。實(shí)測中,緩沖池命中率從98%降至90%時(shí),P99查詢延遲從12ms上升至85ms(7倍惡化)。增加緩沖池大小是最直接有效的優(yōu)化手段。

讀寫分離架構(gòu)有效性的證據(jù)鏈:在典型的讀寫比例7:3的OLTP場景中,配置ProxySQL將讀請(qǐng)求分散到3個(gè)從庫,主庫寫壓力降低60%,讀請(qǐng)求平均延遲從35ms降低到8ms(因?yàn)閺膸鞜o寫負(fù)載且可配置更大緩沖池)。

慢查詢治理是一場持續(xù)戰(zhàn),不存在一勞永逸的解決方案。最好的慢查詢優(yōu)化是預(yù)防:在上線前強(qiáng)制執(zhí)行EXPLAIN審查,在生產(chǎn)環(huán)境持續(xù)監(jiān)控慢查詢?nèi)罩荆瑢?duì)新功能的SQL進(jìn)行性能評(píng)估。只有將慢查詢治理流程化、自動(dòng)化,才能真正將數(shù)據(jù)庫性能維持在健康水平。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 數(shù)據(jù)庫
    +關(guān)注

    關(guān)注

    7

    文章

    4068

    瀏覽量

    68477
  • MySQL
    +關(guān)注

    關(guān)注

    1

    文章

    924

    瀏覽量

    29698

原文標(biāo)題:MySQL數(shù)據(jù)庫慢查詢分析與優(yōu)化實(shí)戰(zhàn)

文章出處:【微信號(hào):magedu-Linux,微信公眾號(hào):馬哥Linux運(yùn)維】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    分析一下MySQL數(shù)據(jù)庫與ElasticSearch的實(shí)際應(yīng)用

    就要根據(jù)用戶的查找內(nèi)容去構(gòu)建對(duì)應(yīng)檢索數(shù)據(jù)的語句,這條語句往往是多表查詢的,模糊查詢的操作,十分耗費(fèi)系統(tǒng)資源,更何況是在一些并發(fā)情況下,系統(tǒng)的性能就很低了,流程可見下圖:此外,數(shù)據(jù)庫處理
    發(fā)表于 06-15 17:15

    基于數(shù)據(jù)庫查詢過程優(yōu)化設(shè)計(jì)

    在大型關(guān)系數(shù)據(jù)庫管理與開發(fā)中,優(yōu)化設(shè)計(jì)極大地提高數(shù)據(jù)庫的性能。通過對(duì)一大型數(shù)據(jù)庫查詢語句執(zhí)行過程的討論,提出了對(duì)同一表格進(jìn)行多個(gè)選擇運(yùn)算的
    發(fā)表于 02-27 16:05 ?18次下載

    基于語義指向性分析數(shù)據(jù)庫訪問查詢優(yōu)化設(shè)計(jì)

    基于語義指向性分析數(shù)據(jù)庫訪問查詢優(yōu)化設(shè)計(jì)_馬曉珺
    發(fā)表于 01-03 17:41 ?0次下載

    基于Greenplum數(shù)據(jù)庫查詢優(yōu)化

    針對(duì)分布式數(shù)據(jù)庫查詢效率隨著數(shù)據(jù)規(guī)模的增大而降低的問題,以Greenplum分布式數(shù)據(jù)庫為研究對(duì)象,從優(yōu)化
    發(fā)表于 03-29 17:46 ?0次下載

    數(shù)據(jù)庫系統(tǒng)概論之如何進(jìn)行關(guān)系查詢處理和查詢優(yōu)化

    本文檔的主要內(nèi)容詳細(xì)介紹的是數(shù)據(jù)庫系統(tǒng)概論之如何進(jìn)行關(guān)系查詢處理和查詢優(yōu)化主要內(nèi)容包括了:1、關(guān)系數(shù)據(jù)庫系統(tǒng)的
    發(fā)表于 11-15 15:12 ?11次下載
    <b class='flag-5'>數(shù)據(jù)庫</b>系統(tǒng)概論之如何進(jìn)行關(guān)系<b class='flag-5'>查詢</b>處理和<b class='flag-5'>查詢</b><b class='flag-5'>優(yōu)化</b>

    MySQL數(shù)據(jù)庫:理解MySQL的性能優(yōu)化、優(yōu)化查詢

    最近一直在為大家更新MySQL相關(guān)學(xué)習(xí)內(nèi)容,可能有朋友不懂MySQL的重要性。在程序,語言,架構(gòu)更新?lián)Q代頻繁的今天,MySQL 恐怕是大家使用最多的存儲(chǔ)數(shù)據(jù)庫了。由于
    的頭像 發(fā)表于 07-02 17:18 ?3750次閱讀
    <b class='flag-5'>MySQL</b><b class='flag-5'>數(shù)據(jù)庫</b>:理解<b class='flag-5'>MySQL</b>的性能<b class='flag-5'>優(yōu)化</b>、<b class='flag-5'>優(yōu)化</b><b class='flag-5'>查詢</b>

    MySQL數(shù)據(jù)庫管理與應(yīng)用

    MySQL數(shù)據(jù)庫管理與應(yīng)用 MySQL是一種廣泛使用的關(guān)系型數(shù)據(jù)庫管理系統(tǒng),被認(rèn)為是最流行和最常見的開源數(shù)據(jù)庫之一。它可以被用于多種不同的應(yīng)
    的頭像 發(fā)表于 08-28 17:15 ?1884次閱讀

    MySQL數(shù)據(jù)庫基礎(chǔ)知識(shí)

    的基礎(chǔ)知識(shí),包括其架構(gòu)、數(shù)據(jù)類型、表操作、查詢語句和數(shù)據(jù)導(dǎo)入導(dǎo)出等方面。 MySQL 數(shù)據(jù)庫架構(gòu) MyS
    的頭像 發(fā)表于 11-21 11:09 ?1957次閱讀

    數(shù)據(jù)庫數(shù)據(jù)恢復(fù)—MYSQL數(shù)據(jù)庫ibdata1文件損壞的數(shù)據(jù)恢復(fù)案例

    mysql數(shù)據(jù)庫故障: mysql數(shù)據(jù)庫文件ibdata1、MYI、MYD損壞。 故障表現(xiàn):1、數(shù)據(jù)庫無法進(jìn)行
    的頭像 發(fā)表于 12-09 11:05 ?1351次閱讀

    數(shù)據(jù)庫數(shù)據(jù)恢復(fù)—Mysql數(shù)據(jù)庫表記錄丟失的數(shù)據(jù)恢復(fù)流程

    Mysql數(shù)據(jù)庫故障: Mysql數(shù)據(jù)庫表記錄丟失。 Mysql數(shù)據(jù)庫故障表現(xiàn): 1、
    的頭像 發(fā)表于 12-16 11:05 ?1307次閱讀
    <b class='flag-5'>數(shù)據(jù)庫</b><b class='flag-5'>數(shù)據(jù)</b>恢復(fù)—<b class='flag-5'>Mysql</b><b class='flag-5'>數(shù)據(jù)庫</b>表記錄丟失的<b class='flag-5'>數(shù)據(jù)</b>恢復(fù)流程

    MySQL數(shù)據(jù)庫的安裝

    MySQL數(shù)據(jù)庫的安裝 【一】各種數(shù)據(jù)庫的端口 MySQL :3306 Redis :6379 MongoDB :27017 Django :8000 flask :5000 【二】
    的頭像 發(fā)表于 01-14 11:25 ?1186次閱讀
    <b class='flag-5'>MySQL</b><b class='flag-5'>數(shù)據(jù)庫</b>的安裝

    MySQL數(shù)據(jù)庫是什么

    MySQL數(shù)據(jù)庫是一種 開源的關(guān)系型數(shù)據(jù)庫管理系統(tǒng)(RDBMS) ,由瑞典MySQL AB公司開發(fā),后被Oracle公司收購。它通過結(jié)構(gòu)化查詢
    的頭像 發(fā)表于 05-23 09:18 ?1359次閱讀

    企業(yè)級(jí)MySQL數(shù)據(jù)庫管理指南

    在當(dāng)今數(shù)字化時(shí)代,MySQL作為全球最受歡迎的開源關(guān)系型數(shù)據(jù)庫,承載著企業(yè)核心業(yè)務(wù)數(shù)據(jù)的存儲(chǔ)與處理。作為數(shù)據(jù)庫管理員(DBA),掌握MySQL
    的頭像 發(fā)表于 07-09 09:50 ?831次閱讀

    MySQL查詢終極優(yōu)化指南

    作為一名在生產(chǎn)環(huán)境摸爬滾打多年的運(yùn)維工程師,我見過太多因?yàn)?b class='flag-5'>慢查詢導(dǎo)致的線上故障。今天分享一套經(jīng)過實(shí)戰(zhàn)檢驗(yàn)的MySQL
    的頭像 發(fā)表于 08-13 15:55 ?922次閱讀

    數(shù)據(jù)庫查詢分析與SQL優(yōu)化實(shí)戰(zhàn)技巧

    今天,我將分享我在處理數(shù)千次數(shù)據(jù)庫性能問題中積累的實(shí)戰(zhàn)經(jīng)驗(yàn),幫助你系統(tǒng)掌握查詢分析與SQL優(yōu)化
    的頭像 發(fā)表于 09-08 09:34 ?1153次閱讀