亚洲国产日韩欧美一区二区三区,精品亚洲国产成人av在线,国产99视频精品免视看7,99国产精品久久久久久久成人热,欧美日韩亚洲国产综合乱

搜索

解決Oracle JDBC Template參數(shù)化查詢性能瓶頸:物化視圖實(shí)踐

心靈之曲
發(fā)布: 2025-10-17 13:30:22
原創(chuàng)
249人瀏覽過

解決Oracle JDBC Template參數(shù)化查詢性能瓶頸:物化視圖實(shí)踐

本文探討了在spring boot中使用jdbc template查詢oracle數(shù)據(jù)庫(kù)時(shí),參數(shù)化查詢導(dǎo)致性能急劇下降的問題。即使已建立索引,面對(duì)千萬級(jí)數(shù)據(jù)仍可能出現(xiàn)數(shù)分鐘的延遲。核心解決方案是利用oracle物化視圖進(jìn)行數(shù)據(jù)預(yù)計(jì)算和緩存,并通過定時(shí)刷新策略確保數(shù)據(jù)時(shí)效性,從而將查詢響應(yīng)時(shí)間從數(shù)分鐘縮短至數(shù)百毫秒。

在現(xiàn)代企業(yè)級(jí)應(yīng)用中,數(shù)據(jù)庫(kù)查詢性能是至關(guān)重要的一環(huán)。當(dāng)處理大規(guī)模數(shù)據(jù)集時(shí),即使是看似簡(jiǎn)單的查詢,也可能因?yàn)槎喾N因素而導(dǎo)致性能瓶頸。本文將深入探討一個(gè)常見的問題:在使用Spring Boot的JDBC Template對(duì)Oracle數(shù)據(jù)庫(kù)進(jìn)行參數(shù)化查詢時(shí),面對(duì)數(shù)千萬級(jí)別的數(shù)據(jù)量,即使相關(guān)字段已建立索引,查詢響應(yīng)時(shí)間仍可能從數(shù)百毫秒激增至數(shù)分鐘。我們將提供一種行之有效的解決方案:利用Oracle物化視圖(Materialized View)。

問題描述

假設(shè)我們有一個(gè)查詢,用于從 CONTRACT 和 CLIENT_EXTRA_INFO 表中檢索客戶信息,并根據(jù)手機(jī)號(hào)、合同狀態(tài)和標(biāo)志進(jìn)行過濾,同時(shí)限制返回的記錄數(shù)。

原始SQL查詢(在數(shù)據(jù)庫(kù)控制臺(tái)執(zhí)行快速):

SELECT
    CLIENT_EXTRA_INFO.CLIENT_NUMBER,
    CLIENT_EXTRA_INFO.FULL_NAME
FROM
     CONTRACT
        JOIN CLIENT_EXTRA_INFO on (CONTRACT.CLIENTID = CLIENT_EXTRA_INFO.ID)
WHERE
    CLIENT_EXTRA_INFO.MBPHONE = '0343423223'
  and CONTRACT.STATUS = 'ACTIVE'
  and CONTRACT.FLAG IN ('2', '5')
FETCH  FIRST  10 ROWS ONLY;
登錄后復(fù)制

當(dāng)此查詢?cè)跀?shù)據(jù)庫(kù)控制臺(tái)直接執(zhí)行時(shí),響應(yīng)時(shí)間可能僅為數(shù)百毫秒。然而,當(dāng)通過Spring Boot的JDBC Template(例如 NamedParameterJdbcTemplate)使用參數(shù)化查詢時(shí),性能卻急劇下降。

Java代碼示例(使用參數(shù)化查詢導(dǎo)致性能問題):

// ... 省略部分代碼
String sql ="SELECT\n" +
        "    CLIENT_EXTRA_INFO.CLIENT_NUMBER,\n" +
        "    CLIENT_EXTRA_INFO.FULL_NAME,\n" +
        "FROM\n" +
        "     CONTRACT\n" +
        "        JOIN CLIENT_EXTRA_INFO on (CONTRACT.CLIENTID = CLIENT_EXTRA_INFO.ID)\n" +
        "WHERE\n" +
        "    CLIENT_EXTRA_INFO.MBPHONE = :phone\n" +
        "  and CONTRACT.STATUS = 'ACTIVE'\n" +
        "  and CONTRACT.FLAG IN ('2', '5')\n" +
        "FETCH  FIRST  :row ROWS ONLY";

MapSqlParameterSource mapSqlParameterSource = new MapSqlParameterSource();
mapSqlParameterSource.addValue("phone", request.getPhoneNumber());
mapSqlParameterSource.addValue("row", request.getSize());

// pulseOpsTemplateJdbc.query(...) 執(zhí)行時(shí)耗時(shí)數(shù)分鐘
// ...
登錄后復(fù)制

盡管 CLIENT_EXTRA_INFO.MBPHONE、CONTRACT.STATUS 和 CONTRACT.FLAG 等字段都已建立索引,但在處理包含8000萬條記錄的表時(shí),參數(shù)化查詢的響應(yīng)時(shí)間可能長(zhǎng)達(dá)7分鐘,這在生產(chǎn)環(huán)境中是無法接受的。

解決方案:利用Oracle物化視圖

面對(duì)此類性能挑戰(zhàn),物化視圖(Materialized View,簡(jiǎn)稱MV)是一個(gè)強(qiáng)大的工具。物化視圖是數(shù)據(jù)庫(kù)中的一個(gè)物理存儲(chǔ)對(duì)象,它包含了一個(gè)查詢的結(jié)果集。與普通視圖不同,物化視圖的數(shù)據(jù)是預(yù)先計(jì)算并存儲(chǔ)的,因此查詢物化視圖通常比執(zhí)行原始復(fù)雜查詢要快得多。

1. 創(chuàng)建物化視圖

首先,我們需要根據(jù)導(dǎo)致性能問題的原始查詢來創(chuàng)建一個(gè)物化視圖??紤]到原始查詢的復(fù)雜性和過濾條件,我們可以創(chuàng)建一個(gè)包含預(yù)計(jì)算結(jié)果的物化視圖。

物化視圖創(chuàng)建示例:

CREATE MATERIALIZED VIEW MV_CLIENT_CONTRACT_INFO
BUILD IMMEDIATE
REFRESH COMPLETE ON DEMAND
AS
SELECT
    CLIENT_EXTRA_INFO.CLIENT_NUMBER,
    CLIENT_EXTRA_INFO.FULL_NAME,
    CLIENT_EXTRA_INFO.MBPHONE,  -- 將查詢條件中的字段也包含進(jìn)來,方便后續(xù)查詢
    CONTRACT.STATUS,
    CONTRACT.FLAG
FROM
     CONTRACT
        JOIN CLIENT_EXTRA_INFO on (CONTRACT.CLIENTID = CLIENT_EXTRA_INFO.ID)
WHERE
    CONTRACT.STATUS = 'ACTIVE'
  and CONTRACT.FLAG IN ('2', '5');
登錄后復(fù)制

說明:

  • MV_CLIENT_CONTRACT_INFO 是物化視圖的名稱。
  • BUILD IMMEDIATE 表示在創(chuàng)建時(shí)立即填充數(shù)據(jù)。
  • REFRESH COMPLETE ON DEMAND 指定了刷新方式。COMPLETE 表示每次刷新都完全重新計(jì)算所有數(shù)據(jù),ON DEMAND 表示需要手動(dòng)或通過調(diào)度器觸發(fā)刷新。這里沒有使用 FAST REFRESH 是因?yàn)樵疾樵儼?JOIN 和 WHERE 子句,可能不滿足快速刷新的條件,或者為了簡(jiǎn)化起見,我們選擇完全刷新。
  • 我們將原始查詢中的所有相關(guān)字段都包含在物化視圖中,特別是那些作為過濾條件的字段(如 MBPHONE、STATUS、FLAG),以便在查詢物化視圖時(shí)能直接利用這些字段。

2. 對(duì)物化視圖建立索引

為了進(jìn)一步優(yōu)化對(duì)物化視圖的查詢性能,特別是當(dāng)物化視圖被用作查詢的源表時(shí),在其上創(chuàng)建索引是必不可少的。根據(jù)原始查詢的過濾條件,我們應(yīng)該在 MBPHONE 字段上建立索引。

360智圖
360智圖

AI驅(qū)動(dòng)的圖片版權(quán)查詢平臺(tái)

360智圖38
查看詳情 360智圖

物化視圖索引創(chuàng)建示例:

CREATE INDEX IDX_MV_CLIENT_CONTRACT_INFO_PHONE ON MV_CLIENT_CONTRACT_INFO (MBPHONE);
登錄后復(fù)制

3. 刷新策略與調(diào)度

由于物化視圖的數(shù)據(jù)是預(yù)先計(jì)算的,它可能不會(huì)實(shí)時(shí)反映基礎(chǔ)表的變化。根據(jù)業(yè)務(wù)對(duì)數(shù)據(jù)新鮮度的要求,我們需要制定一個(gè)刷新策略。在本例中,原問題提到“create scheduler to reset it every 24h”,這表明數(shù)據(jù)允許有一定的延遲,每天刷新一次是可接受的。

我們可以使用Oracle的 DBMS_SCHEDULER 包來創(chuàng)建一個(gè)定時(shí)任務(wù),每天自動(dòng)刷新物化視圖。

創(chuàng)建物化視圖刷新調(diào)度器示例:

-- 1. 創(chuàng)建一個(gè)程序,用于刷新物化視圖
BEGIN
  DBMS_SCHEDULER.CREATE_PROGRAM (
    program_name        => 'REFRESH_MV_CLIENT_CONTRACT_INFO_PRG',
    program_type        => 'STORED_PROCEDURE',
    program_action      => 'DBMS_MVIEW.REFRESH',
    number_of_arguments => 1,
    enabled             => FALSE
  );

  DBMS_SCHEDULER.DEFINE_PROGRAM_ARGUMENT (
    program_name      => 'REFRESH_MV_CLIENT_CONTRACT_INFO_PRG',
    argument_position => 1,
    argument_name     => 'list',
    argument_type     => 'VARCHAR2'
  );

  DBMS_SCHEDULER.ENABLE ('REFRESH_MV_CLIENT_CONTRACT_INFO_PRG');
END;
/

-- 2. 創(chuàng)建一個(gè)任務(wù),調(diào)用上述程序并設(shè)置調(diào)度計(jì)劃
BEGIN
  DBMS_SCHEDULER.CREATE_JOB (
    job_name        => 'DAILY_REFRESH_MV_CLIENT_CONTRACT_INFO_JOB',
    program_name    => 'REFRESH_MV_CLIENT_CONTRACT_INFO_PRG',
    start_date      => SYSTIMESTAMP, -- 立即開始調(diào)度
    repeat_interval => 'FREQ=DAILY;BYHOUR=3', -- 每天凌晨3點(diǎn)執(zhí)行
    end_date        => NULL,
    enabled         => TRUE,
    auto_drop       => FALSE,
    comments        => 'Daily refresh for MV_CLIENT_CONTRACT_INFO'
  );

  -- 設(shè)置程序參數(shù)
  DBMS_SCHEDULER.SET_JOB_ARGUMENT_VALUE (
    job_name      => 'DAILY_REFRESH_MV_CLIENT_CONTRACT_INFO_JOB',
    argument_position => 1,
    argument_value  => 'MV_CLIENT_CONTRACT_INFO'
  );
END;
/
登錄后復(fù)制

上述代碼創(chuàng)建了一個(gè)名為 DAILY_REFRESH_MV_CLIENT_CONTRACT_INFO_JOB 的調(diào)度任務(wù),它將每天凌晨3點(diǎn)執(zhí)行 DBMS_MVIEW.REFRESH('MV_CLIENT_CONTRACT_INFO') 來完全刷新物化視圖。

4. 修改應(yīng)用查詢邏輯

一旦物化視圖創(chuàng)建并設(shè)置好刷新機(jī)制,應(yīng)用層的查詢邏輯就需要進(jìn)行修改,以查詢物化視圖而不是原始表。

新的查詢SQL(查詢物化視圖):

SELECT
    CLIENT_NUMBER,
    FULL_NAME
FROM
     MV_CLIENT_CONTRACT_INFO
WHERE
    MBPHONE = :phone
FETCH  FIRST  :row ROWS ONLY;
登錄后復(fù)制

Java代碼示例(查詢物化視圖):

// ... 省略部分代碼
String sql ="SELECT\n" +
        "    CLIENT_NUMBER,\n" +
        "    FULL_NAME\n" +
        "FROM\n" +
        "     MV_CLIENT_CONTRACT_INFO\n" +
        "WHERE\n" +
        "    MBPHONE = :phone\n" +
        "FETCH  FIRST  :row ROWS ONLY";

MapSqlParameterSource mapSqlParameterSource = new MapSqlParameterSource();
mapSqlParameterSource.addValue("phone", request.getPhoneNumber());
mapSqlParameterSource.addValue("row", request.getSize());

// pulseOpsTemplateJdbc.query(...) 現(xiàn)在將查詢物化視圖,性能將顯著提升
// ...
登錄后復(fù)制

通過這種方式,查詢不再需要執(zhí)行復(fù)雜的JOIN和過濾操作,而是直接從預(yù)計(jì)算的物化視圖中檢索數(shù)據(jù),極大地提升了查詢性能。

注意事項(xiàng)與總結(jié)

  1. 數(shù)據(jù)新鮮度與刷新頻率: 物化視圖的刷新頻率應(yīng)根據(jù)業(yè)務(wù)對(duì)數(shù)據(jù)新鮮度的要求來確定。頻繁刷新會(huì)增加數(shù)據(jù)庫(kù)的負(fù)載,而不頻繁刷新則可能導(dǎo)致數(shù)據(jù)不一致。
  2. 存儲(chǔ)空間: 物化視圖會(huì)占用額外的存儲(chǔ)空間,尤其是在預(yù)計(jì)算大量數(shù)據(jù)時(shí)。
  3. 刷新開銷: 每次刷新(特別是 COMPLETE 刷新)都需要重新計(jì)算數(shù)據(jù),這可能是一個(gè)耗時(shí)的操作,應(yīng)在業(yè)務(wù)低峰期進(jìn)行。
  4. 物化視圖索引: 像對(duì)待普通表一樣,在物化視圖上創(chuàng)建合適的索引對(duì)于提高查詢性能至關(guān)重要。
  5. 查詢改寫: 確保應(yīng)用層的查詢邏輯已正確地指向物化視圖,并且查詢條件能夠有效利用物化視圖中的數(shù)據(jù)和索引。
  6. 快速刷新(FAST REFRESH): 如果原始查詢滿足特定條件(例如不包含某些聚合函數(shù)、JOIN類型等),可以考慮使用 FAST REFRESH 方式,它只應(yīng)用基礎(chǔ)表的增量變化,通常比 COMPLETE REFRESH 更高效。但在本例的復(fù)雜查詢中,COMPLETE REFRESH 可能是更穩(wěn)妥的選擇。

通過引入物化視圖,我們成功地將一個(gè)耗時(shí)數(shù)分鐘的JDBC Template參數(shù)化查詢優(yōu)化到數(shù)百毫秒的響應(yīng)時(shí)間。這表明在處理大規(guī)模數(shù)據(jù)集和復(fù)雜查詢時(shí),合理利用數(shù)據(jù)庫(kù)特性,如物化視圖,是解決性能瓶關(guān)鍵的有效策略。

以上就是解決Oracle JDBC Template參數(shù)化查詢性能瓶頸:物化視圖實(shí)踐的詳細(xì)內(nèi)容,更多請(qǐng)關(guān)注php中文網(wǎng)其它相關(guān)文章!

數(shù)碼產(chǎn)品性能查詢
數(shù)碼產(chǎn)品性能查詢

該軟件包括了市面上所有手機(jī)CPU,手機(jī)跑分情況,電腦CPU,電腦產(chǎn)品信息等等,方便需要大家查閱數(shù)碼產(chǎn)品最新情況,了解產(chǎn)品特性,能夠進(jìn)行對(duì)比選擇最具性價(jià)比的商品。

下載
來源:php中文網(wǎng)
本文內(nèi)容由網(wǎng)友自發(fā)貢獻(xiàn),版權(quán)歸原作者所有,本站不承擔(dān)相應(yīng)法律責(zé)任。如您發(fā)現(xiàn)有涉嫌抄襲侵權(quán)的內(nèi)容,請(qǐng)聯(lián)系admin@php.cn
最新問題
開源免費(fèi)商場(chǎng)系統(tǒng)廣告
最新下載
更多>
網(wǎng)站特效
網(wǎng)站源碼
網(wǎng)站素材
前端模板
關(guān)于我們 免責(zé)申明 意見反饋 講師合作 廣告合作 最新更新
php中文網(wǎng):公益在線php培訓(xùn),幫助PHP學(xué)習(xí)者快速成長(zhǎng)!
關(guān)注服務(wù)號(hào) 技術(shù)交流群
PHP中文網(wǎng)訂閱號(hào)
每天精選資源文章推送
PHP中文網(wǎng)APP
隨時(shí)隨地碎片化學(xué)習(xí)
PHP中文網(wǎng)抖音號(hào)
發(fā)現(xiàn)有趣的

Copyright 2014-2025 http://ipnx.cn/ All Rights Reserved | php.cn | 湘ICP備2023035733號(hào)