<bdo id="ks4iu"><del id="ks4iu"></del></bdo>
  • 
    <pre id="ks4iu"></pre>
  • <bdo id="ks4iu"><del id="ks4iu"></del></bdo>
    <input id="ks4iu"><em id="ks4iu"></em></input>
    
    
  • <center id="ks4iu"><cite id="ks4iu"></cite></center>
  • 首頁 > 空調(diào) >

    天天快消息!遇到慢SQL該怎么辦?(下)

    來源 | OSCHINA 社區(qū)


    (資料圖片)

    作者 | Gauss松鼠會

    原文鏈接:https://my.oschina.net/gaussdb/blog/5553522

    在數(shù)據(jù)庫的日常使用中,難免會遇到慢 SQL,遇到慢 SQL 本身并不可怕,困難之處在于如何識別慢 SQL 并對其優(yōu)化,使它不至于拖慢整個系統(tǒng)的性能,避免危害到日常業(yè)務(wù)的正常進(jìn)行。

    上期我們講了索引原因、系統(tǒng)配置和資源競爭導(dǎo)致的慢 SQL,今天我們繼續(xù)分析和總結(jié)。

    目錄

    表本身包含大量數(shù)據(jù)

    SQL 語句寫得很差

    總結(jié)

    表本身包含大量數(shù)據(jù)

    盡管 openGauss 對于大的行存表處理性能非常優(yōu)秀,但表本身的數(shù)據(jù)情況依然是導(dǎo)致慢 SQL 的重要原因。一般來說,具有以下幾種情況:

    1. 表的數(shù)據(jù)量很大,且很少被緩存,導(dǎo)致語句需要掃描的元組很多;

    2. 表的數(shù)據(jù)量很大,在修改、刪除數(shù)據(jù)時需要修改較多的元組;

    3. 向表中插入的數(shù)據(jù)量很大;

    4. 業(yè)務(wù)上需要檢索出的數(shù)據(jù)量很多;

    5. 頻繁的數(shù)據(jù)修改,導(dǎo)致表中存在很多死元組(dead tuple),影響掃描性能;

    表的數(shù)據(jù)量較大導(dǎo)致的慢 SQL 問題,一般需要從業(yè)務(wù)上進(jìn)行入手,直接通過修改數(shù)據(jù)庫來達(dá)到優(yōu)化慢 SQL 的目的是很難實(shí)現(xiàn)的。因此,需要用戶分析具體的業(yè)務(wù),對業(yè)務(wù)數(shù)據(jù)進(jìn)行冷熱分離、分庫分表、使用分布式中間件等。如果希望在數(shù)據(jù)庫層進(jìn)行優(yōu)化,則可以通過增加宿主機(jī)的內(nèi)存,進(jìn)而增加 max_process_memory、shared_buffers、work_mem 等的大小;使用性能更佳的磁盤;適當(dāng)創(chuàng)建索引;使用表空間調(diào)整磁盤布局等。

    SQL 語句寫得很差

    由 SQL 語句寫法問題導(dǎo)致的慢 SQL 也相對多見,這類寫得比較差的慢 SQL 也被俗稱為 “爛 SQL”。多數(shù)情況都下,由 “爛 SQL” 導(dǎo)致的索引失效的問題較多,對于這種情況,可參考前面的描述對 SQL 語句進(jìn)行改寫,使其能夠使用到索引。

    除了修改慢 SQL 使其能夠使用索引,下面還列出了幾種比較常見的、可能優(yōu)化 openGauss 數(shù)據(jù)庫性能的 SQL 改寫規(guī)則:

    改寫規(guī)則

    改寫條件

    改寫說明

    原始查詢語句示例

    改寫后語句示例

    將"select distinct *" 改寫為"select *"

    所查詢表格含唯一列或主鍵

    通過確定 tuple 無重復(fù),去掉 distinct,從而省去去重步驟,提升效率

    select distinct * from bmsql_customer limit 10;

    select * from bmsql_customer limit 10;

    將 having 子句中條件放到 where 子句中

    -

    將謂詞表達(dá)式提前,可有效縮減 group 時的數(shù)據(jù)集

    select cfg_name from bmsql_config group by cfg_name having cfg_name="1"

    select cfg_name from bmsql_config where cfg_name = "1" group by cfg_name

    簡化 where 子句中謂詞表達(dá)式

    -

    某些復(fù)雜謂詞無法有效觸發(fā) openGauss 內(nèi)的 rewrite 邏輯,無法使用索引掃描

    select o_w_id, o_d_id, o_id, o_c_id from bmsql_oorder where o_w_id + 1> 3

    select o_w_id, o_d_id, o_id, o_c_id from bmsql_oorder where o_w_id > 2

    將 order by 或 group by 中的無用列去掉

    group by 或 order by 涉及的列包含在 where 子句中的等值表達(dá)式中

    去掉無用字段,SQL 更為簡潔

    select cfg_name from bmsql_config where cfg_name="2" group by cfg_name order by cfg_name, cfg_value

    select cfg_name from bmsql_config where cfg_name = "2" order by cfg_value

    去掉 where 子句中永為真的表達(dá)式

    -

    去掉無用字段,SQL 更為簡潔

    select * from bmsql_config where 1=1 and 2=2 limit 10

    select * from bmsql_config limit 10

    將 union 轉(zhuǎn)換為 union all

    -

    避免了去重帶來的執(zhí)行代價

    select * from bmsql_config union select * from bmsql_config

    select * from bmsql_config union all select * from bmsql_config

    將 delete 語句轉(zhuǎn)換為 truncate 語句

    無 where 子句

    將 DML 語句轉(zhuǎn)換為 DDL 語句,一次性回收表空間,執(zhí)行速度更快

    delete from bmsql_config

    truncate table bmsql_config

    將 where 子句中 "or" 連接的等式轉(zhuǎn)換為 "in" 結(jié)構(gòu)

    -

    "in" 結(jié)構(gòu)可加快過濾速度

    select * from bmsql_stock where s_w_id=10 or s_w_id=1 or s_w_id=100 or s_i_id=1 or s_i_id=10

    select * from bmsql_stock where s_w_id in (1,10,100) or s_i_id in(1,10)

    將 self join 查詢拆分為效率更高兩個子查詢

    1) self join 查詢。

    2) where 子句包含相同列差值的范圍查詢。

    例如 1

    通過等值謂詞加快查詢速度

    select a.c_id from bmsql_customer a, bmsql_customer b where a.c_id - b.c_id <= 20 and a.c_id > b.c_id

    select * from (select a.c_id from bmsql_customer as a, bmsql_customer as b where trunc((a.c_id) / 20) = trunc(b.c_id / 20) and a.c_id > b.c_id union all select a.c_id from bmsql_customer as a, bmsql_customer as b where trunc((a.c_id) / 20) = trunc(b.c_id / 20 + 1) and a.c_id - b.c_id <= 20)

    對于業(yè)務(wù)系統(tǒng),SQL 語句上線之前的審計工作基本都可以覆蓋上述的場景,業(yè)內(nèi)也具備很多對 SQL 語句進(jìn)行改寫的工具,不過這些工具的一些改寫規(guī)則并不是絕對意義上的等值改寫。而且,很多改寫條件對于 openGauss 來說不見得有效,因?yàn)?openGauss 在數(shù)據(jù)庫內(nèi)部也存在 rewrite 邏輯。

    DBMind 平臺會進(jìn)一步演進(jìn) SQL 語句的智能改寫功能,提供給用戶在線的交互式智能查詢改寫能力,預(yù)計在未來的版本中與用戶見面。

    總結(jié)

    我們在上面已經(jīng)列出了能夠?qū)е侣?SQL 的原因,基本覆蓋了在 openGauss 上造成慢 SQL 的大多數(shù)原因。不過,one-by-one 手動地進(jìn)行慢 SQL 檢查對于用戶來說工作量確實(shí)太大。故而,openGauss 的 DBMind 功能本身已經(jīng)集成了對慢 SQL 進(jìn)行智能根因識別的能力,用戶可以通過運(yùn)行下述命令在后臺啟動慢 SQL 根因分析功能(需要首先部署 Prometheus 以及 expoter,以便能夠采集到監(jiān)控指標(biāo)):

    gs_dbmind service start-c confpath --only-run slow_query_diagnosis

    注:顯式指定 --only-run 參數(shù)可以僅啟動被選擇的 DBMind 服務(wù)項

    被診斷后的慢 SQL 會存儲在元數(shù)據(jù)庫(存放診斷結(jié)果的數(shù)據(jù)庫)中,用戶可以通過下述命令查看:

    gs_dbmind component slow_query_diagnosis show -c confpath --query SQL --start-timetimestamps0--end-timetimestamps1

    也可以通過與 Grafana 聯(lián)合來展示慢 SQL 的分析結(jié)果,DBMind 也提供了簡單的 Grafana 配置模板,可供用戶參考:

    https://github.com/opengauss-mirror/openGauss-server/blob/master/src/gausskernel/dbmind/tools/misc/grafana-template-slow-query-analysis.json

    由于openGauss 官方網(wǎng)站的發(fā)行包中的 DBMind 可能滯后于代碼托管平臺(gitee 或 github)上的最新代碼,直接編譯 openGauss 又需要花費(fèi)很多的時間。故而,如果用戶只是想單純提取最新的 DBMind 功能,可以通過下面的 Linux 命令來實(shí)現(xiàn):

    gitclone -b master --depth 1 https://gitee.com/opengauss/openGauss-server.gitcdopenGauss-server/src/gausskernel/dbmind/mvtools dbmindtarzcf dbmind.tar.gz gs_dbmind dbmind

    生成的 dbmind.tar.gz 壓縮包在合適的部署位置解壓即可。

    當(dāng)然,如果用戶希望手動檢查一下慢 SQL 的原因,也可以根據(jù)附表的檢查項來檢查慢 SQL 的產(chǎn)生原因。

    附表:慢 SQL 檢查列表

    檢查項

    檢查方式(系統(tǒng)表或系統(tǒng)視圖)

    檢查方法

    語句執(zhí)行時存在鎖競爭

    dbe_perf.statement_history(start_time,finish_time, query)、pg_locks(pid, mode, locktype, grant)、pg_stat_activity(xact_start, query_start, query, pid)

    查詢在語句執(zhí)行期間是否被阻塞。

    表中死元組占比超過設(shè)定閾值

    dbe_perf.statement_history(query, dbname, schemaname)

    pg_stat_users_tables(relname, schemaname,n_live_tup, n_dead_tup)

    n_dead_tup /n_live_tup,占比超過閾值則認(rèn)為表過度膨脹 (默認(rèn)閾值:0.2)。

    語句掃描行數(shù)較多

    dbe_perf.statement_history(n_tuples_fetched, n_tuples_returned, n_live_tup, n_dead_tup)

    n_tuples_fetched+n_tuples_returned,超過閾值則認(rèn)為過大(默認(rèn)閾值:10000)。

    語句緩存命中率較低

    dbe_perf.statement_history(n_blocks_fetched, n_blocks_hit)

    n_block_hit /n_block_fetched,小于閾值則認(rèn)為較低(默認(rèn)閾值:0.95)

    慢 SQL (delete、insert、update) 相關(guān)表存在冗余索引

    dbe_perf.statement_history(dbname, schemaname, query), pg_stat_user_indexes(schemaname, relname, indexrelname, idx_scan, idx_tup_read, idx_tup_fetch)

    pg_indexes(schemaname, tablename, indexname, indexdef)

    SQL 相關(guān)表滿足:① 不是唯一索引;② (idx_scan, idx_tup_read,idx_tup_fetch)=(0,0,0);③ 索引不在數(shù)據(jù)庫的("pg_catalog", "information_schema","snapshot", "dbe_pldeveloper")schema 下。如果滿足則認(rèn)為次索引為冗余索引,否則為有效索引。

    更新數(shù)據(jù)量較多

    dbe_perf.statement_history(query, n_tuples_updated)

    pg_stat_user_tables(n_live_tup, n_dead_tup)

    n_tuples_updated 超過閾值則認(rèn)為更新數(shù)據(jù)量較多(默認(rèn)閾值:1000)。

    插入數(shù)據(jù)量較多

    dbe_perf.statement_history(query, n_tuples_inserted)

    pg_stat_user_tables(n_live_tup, n_dead_tup)

    n_tuples_inserted 超過閾值則認(rèn)為插入數(shù)據(jù)量較多(默認(rèn)閾值:1000)。

    刪除數(shù)據(jù)量較多

    dbe_perf.statement_history(query, n_tuples_deleted)

    pg_stat_user_tables(n_live_tup, n_dead_tup)

    n_tuples_deleted 超過閾值則認(rèn)為刪除數(shù)據(jù)量較多(默認(rèn)閾值:1000)。

    相關(guān)表索引個數(shù)較多

    pg_stat_user_indexes(relname,schemaname, indexrelname)

    如果表中索引數(shù)大于閾值并且索引與字段數(shù)比率超過設(shè)定閾值,則認(rèn)為索引數(shù)較多(索引個數(shù)閾值:3,比率默認(rèn)閾值:0.6)。

    執(zhí)行語句發(fā)生落盤(外排序)行為

    dbe_perf.statement(sort_count, sort_spilled_count, sort_mem_used, hash_count, hash_spilled_count, hash_ued_mem, n_calls)

    分析指標(biāo)判斷是否有 hash 或者 order 導(dǎo)致的落盤行為,主要邏輯為:

    1 如果 sort_count 或者 hash_count 不為 0,sort_mem_used 或者 hash_mem_used 為 0,則此 SQL 一定發(fā)生了落盤行為;

    2 如果 sort_spilled_count 或者 hash_spilled_count 不為 0,則執(zhí)行可能發(fā)生落盤行為;

    語句執(zhí)行期間相關(guān)表正在執(zhí)行 AUTOVACUUM 或 AUTOANALYZE 操作

    dbe_perf.statement_history(start_time, finish_time, query)

    pg_stat_user_tables(last_autovacuum, last_autoanalyze)

    執(zhí)行 SQL 期間,正在發(fā)生 vacuum 或者 analyze 行為。

    數(shù)據(jù)庫 TPS 較大

    dbe_perf.statement_history(start_time, finish_time)

    pg_stat_database(datname, xact_commit, xact_rolback)

    相對于正常業(yè)務(wù)時的 TPS,當(dāng)前 TPS 增長較大,則認(rèn)為數(shù)據(jù)庫 TPS 較大;TPS 短期內(nèi)增長異常則認(rèn)為是業(yè)務(wù)風(fēng)暴。

    IOWait 指標(biāo)大于設(shè)定閾值

    系統(tǒng) IOWait 指標(biāo)異常升高

    IOWait 大于用戶設(shè)定閾值(默認(rèn)閾值:10%)

    IOPS 指標(biāo)大于設(shè)定閾值

    系統(tǒng) IOPS 指標(biāo)異常

    IOPS 指標(biāo)大于用戶設(shè)定閾值(默認(rèn)閾值:1000)。

    load average 指標(biāo)大于設(shè)定閾值

    系統(tǒng) load average 指標(biāo)異常

    load average 與服務(wù)器邏輯核數(shù)比率大于用戶設(shè)定閾值(默認(rèn)閾值:0.6)。

    CPU USAGE 指標(biāo)大于設(shè)定閾值

    系統(tǒng) CPU USAGE 指標(biāo)異常

    CPU USAGE 指標(biāo)大于用戶設(shè)定閾值(默認(rèn)閾值:0.6)。

    IOUTILS 指標(biāo)大于設(shè)定閾值

    系統(tǒng) IOUTILS 指標(biāo)異常

    IOUTILS (磁盤利用率) 大于用戶設(shè)定閾值(默認(rèn)閾值:0.5)。

    IOCAPACITY 指標(biāo)大于設(shè)定閾值

    系統(tǒng) IO CAPACITY 指標(biāo)異常

    IOCAPACITY (IO 吞吐量) 大于用戶設(shè)定閾值 (默認(rèn)閾值:50MB/s)。

    IODELAY 指標(biāo)大于設(shè)定閾值

    系統(tǒng) IO DELAY 指標(biāo)異常

    IO DELAY(IO 延遲)大于用戶設(shè)定閾值(默認(rèn)閾值:50ms)。

    網(wǎng)卡丟包率

    系統(tǒng)網(wǎng)卡丟包率異常

    NETWORK DROP RATE 大于用戶設(shè)定閾值(默認(rèn) 0 閾值:0.01)。

    網(wǎng)卡錯誤率

    系統(tǒng)網(wǎng)卡錯誤率異常

    NETWORK ERROR RATE 大于用戶設(shè)定閾值(默認(rèn)閾值:0.01)。

    線程池占用量異常

    dbe_perf.global_threadpool_status

    數(shù)據(jù)庫線程池使用率大于閾值(默認(rèn)閾值:0.95)

    連接池占用量異常

    pg_settings.max_connections,pg_stat_activity

    數(shù)據(jù)庫連接池占用率大于閾值(默認(rèn)閾值:0.8)

    雙寫延遲較大

    dbe_perf.wait_events

    雙寫延遲大于閾值(默認(rèn)閾值:100us)

    表長時間未更新

    pg_stat_user_tables

    表未更新時長超過閾值(默認(rèn)閾值:60s)

    checkpoint 效率低(本規(guī)則僅作為粗略判斷)

    pg_stat_bgwriter

    數(shù)據(jù)庫 buffers_backend 與(buffers_clean+buffers_checkpoint)占比小于閾值(默認(rèn)閾值:1000)

    主備復(fù)制效率較低

    pg_stat_replication

    主備 write_diff、replay_diff、sent_diff 超過閾值(默認(rèn)閾值:500000)

    執(zhí)行計劃存在異常 seqscan 算子

    執(zhí)行計劃

    seqscan 算子代價與總代價比率超過閾值(默認(rèn)閾值:0.3),此特征也會判斷是否缺少相關(guān)索引。

    執(zhí)行計劃存在異常 nestloop 算子

    執(zhí)行計劃

    nestloop 算子代價與總代價比率超過閾值(默認(rèn)閾值:0.3)并且進(jìn)行 nestloop 的結(jié)果集行數(shù)超過閾值(默認(rèn)閾值:10000)。

    執(zhí)行計劃存在異常 hashjoin 算子

    執(zhí)行計劃

    hashjoin 算子代價與總代價比率超過閾值(默認(rèn)閾值:0.3)并且進(jìn)行 hashjoin 的結(jié)果集小于閾值(默認(rèn)閾值:10000)。

    執(zhí)行計劃存在異常 groupagg 算子

    執(zhí)行計劃

    groupagg 算子代價與總代價比率超過閾值(默認(rèn)閾值:0.3)并且執(zhí)行 groupagg 的行數(shù)超過閾值(默認(rèn)閾值:10000)。

    SQL 寫法不優(yōu)

    SQL 文本、pg_stat_user_tables

    SQL 寫法不優(yōu)導(dǎo)致執(zhí)行性能較差

    SQL 執(zhí)行被定時任務(wù)影響

    pg_job,

    dbe_perf.statement_history

    定時任務(wù)執(zhí)行影響了 SQL 執(zhí)行性能,考慮調(diào)整定時任務(wù)時間,避免產(chǎn)生影響。

    執(zhí)行計劃生成時間較長

    dbe_perf.statement_history

    SQL 執(zhí)行計劃生成時間較長。

    參考資料:

    [1].https://www.2ndquadrant.com/en/blog/managing-freezing/

    [2]. http://mysql.taobao.org/monthly/2016/06/03/

    [3].https://www.2ndquadrant.com/en/blog/basics-of-tuning-checkpoints/

    [4]. https://lwn.net/Articles/591723/

    [5].https://dev.mysql.com/doc/refman/8.0/en/glossary.html

    [6].https://github.com/opengauss-mirror/openGauss-server/tree/master/src/gausskernel/dbmind

    END

    PG已碾過MySQL,它真正的對手是Oracle

    這里有最新開源資訊、軟件更新、技術(shù)干貨等內(nèi)容

    點(diǎn)這里 ↓↓↓ 記得 關(guān)注? 標(biāo)星? 哦~

    責(zé)任編輯:Rex_08

    推薦閱讀
    欧美国产在线一区,免费看成年视频网页,国产亚洲福利精品一区,亚洲一区二区约美女探花
    <bdo id="ks4iu"><del id="ks4iu"></del></bdo>
  • 
    <pre id="ks4iu"></pre>
  • <bdo id="ks4iu"><del id="ks4iu"></del></bdo>
    <input id="ks4iu"><em id="ks4iu"></em></input>
    
    
  • <center id="ks4iu"><cite id="ks4iu"></cite></center>
  • 主站蜘蛛池模板: 精品无码人妻一区二区三区品 | 欧美人与动另类在线| 天天做天天爱天天综合网| 台湾香港澳门三级在线| 久久久久亚洲av无码去区首| 精品久久久久久蜜臂a∨| 欧美一线不卡在线播放| 国产精品情侣呻吟对白视频| 亚洲综合色丁香婷婷六月图片| runaway韩国动漫全集在线| 福利体验区试看5次专区| 嫩草影院免费看| 免费A级毛片无码A∨男男| yy一级毛片免费视频| 真实国产乱子伦在线视频不卡| 好爽好多水小荡货护士视频| 免费无码又爽又刺激高潮| h视频在线免费| 狠狠色噜噜狠狠狠狠av| 国语自产偷拍精品视频偷拍| 亚洲欧美日韩天堂一区二区| 69sex久久精品国产麻豆| 欧美日韩精彩视频| 国产精品69白浆在线观看免费| 亚洲av之男人的天堂| 高清一区二区三区日本久| 日本xxx在线播放| 噼里啪啦免费观看高清动漫| 一本色综合久久| 狠狠久久永久免费观看| 国产精品香蕉在线观看不卡| 亚洲av永久无码精品古装片| 高清对白精彩国产国语| 日干夜干天天干| 免费理论片51人人看电影| 99久久无色码中文字幕人妻蜜柚| 欧美成人免费全部观看天天性色| 国产无遮挡色视频免费视频| 久久99精品波多结衣一区| 绝世名器np嗯嗯哦哦粗| 天天摸一摸视频寡妇|