Oracle 數(shù)據(jù)庫(kù)中的 JSON性能注意事項(xiàng)(最佳實(shí)踐)
本文為白皮書(shū)“JSON in Oracle Database: Performance Considerations”的翻譯及閱讀筆記。
目的
本文檔概述了在 Oracle 數(shù)據(jù)庫(kù)中存儲(chǔ)和處理的 JavaScript 對(duì)象表示法 (JSON) 的性能調(diào)優(yōu)最佳實(shí)踐。應(yīng)用這些最佳實(shí)踐將使開(kāi)發(fā)人員、數(shù)據(jù)庫(kù)管理員和架構(gòu)師能夠主動(dòng)避免性能問(wèn)題,并確保他們?cè)O(shè)計(jì)的應(yīng)用程序和系統(tǒng)以最佳性能運(yùn)行。
本文檔中的超鏈接提供文檔、更多信息、示例和免費(fèi)實(shí)踐培訓(xùn)的訪問(wèn)。
Oracle 數(shù)據(jù)庫(kù)中 JSON 的簡(jiǎn)介
2014 年,Oracle 發(fā)布了 Oracle 12.1.0.2,在所有 Oracle 數(shù)據(jù)庫(kù)版本中增加了原生 JSON 支持(這點(diǎn)表示懷疑,應(yīng)該是OSON發(fā)布后才算吧)。在此版本之前,JSON 通常存儲(chǔ)在 NoSQL 數(shù)據(jù)庫(kù)中,而 NoSQL 數(shù)據(jù)庫(kù)缺乏功能和數(shù)據(jù)一致性模型,這迫使開(kāi)發(fā)人員添加額外的代碼來(lái)確保數(shù)據(jù)完整性。
為了彌補(bǔ) NoSQL 的不足,開(kāi)發(fā)人員開(kāi)始使用關(guān)系數(shù)據(jù)庫(kù)或其他數(shù)據(jù)存儲(chǔ)技術(shù),例如運(yùn)行分析查詢。2014 年原生 JSON 支持功能的加入,消除了對(duì)這些額外專(zhuān)用數(shù)據(jù)存儲(chǔ)技術(shù)的需求,從而通過(guò)減少集成工作、簡(jiǎn)化部署、降低風(fēng)險(xiǎn)和成本,顯著加快了開(kāi)發(fā)速度。(融合數(shù)據(jù)庫(kù)的好處)此外,使用標(biāo)準(zhǔn)化 SQL 運(yùn)算符存儲(chǔ)、處理和分析 JSON 顯著縮短了上手時(shí)間,降低了所需的技能,并使非開(kāi)發(fā)人員也能夠輕松處理 JSON 數(shù)據(jù)。
Oracle 數(shù)據(jù)庫(kù)提供原生 JSON 支持。JSON 可與所有 Oracle 數(shù)據(jù)庫(kù)功能兼容,包括選件、Oracle 管理包、框架、架構(gòu)和安全性。存儲(chǔ)在 Oracle 數(shù)據(jù)庫(kù)中的 JSON 還能受益于 Oracle 數(shù)據(jù)庫(kù)的性能、可擴(kuò)展性、可用性、可擴(kuò)展性、可移植性和安全性。(利用Oracle的強(qiáng)大能力也是融合數(shù)據(jù)庫(kù)的好處)訪問(wèn)存儲(chǔ)在 Oracle 數(shù)據(jù)庫(kù)中的 JSON 與訪問(wèn)其他數(shù)據(jù)庫(kù)訪問(wèn)方法(包括 OCI、.NET 和 JDBC)相同。
有關(guān) Oracle 數(shù)據(jù)庫(kù)中 JSON 的更多信息,請(qǐng)參閱 JSON 開(kāi)發(fā)人員指南。
性能特性和技術(shù) – 深入探討
以下部分更詳細(xì)地描述了工作負(fù)載部分中討論的功能:
在 Oracle 數(shù)據(jù)庫(kù)中存儲(chǔ) JSON 數(shù)據(jù)以獲得最佳性能
JSON 可以使用數(shù)據(jù)類(lèi)型為 VARCHAR2、CLOB、BLOB 或 JSON 的列來(lái)存儲(chǔ)。無(wú)論使用哪種類(lèi)型,您都可以像操作其他類(lèi)型的數(shù)據(jù)一樣操作 JSON 數(shù)據(jù)。
- 對(duì)于 Oracle 21c,建議使用針對(duì)查詢和高效(部分)更新進(jìn)行優(yōu)化的原生 JSON 類(lèi)型??梢栽?JSON 列上定義 IS JSON 檢查約束,以強(qiáng)制執(zhí)行正確的 JSON 語(yǔ)法,如果應(yīng)用程序能夠保證 JSON 的正確性,則可以禁用(而不是刪除)該約束。
- 對(duì)于 Oracle 19c,建議使用原生 BLOB 數(shù)據(jù)類(lèi)型,該類(lèi)型也針對(duì)查詢和高效更新進(jìn)行了優(yōu)化。
- CLOB 也受支持,但應(yīng)避免使用,因?yàn)橛捎?UCS2 編碼,CLOBS 通常需要兩倍的存儲(chǔ)空間(和磁盤(pán)讀取)。
- VARCHAR2 字段也受支持,如果已知 JSON 文檔的最大大小,或者 JSON 文檔已存儲(chǔ)在 VARCHAR2 字段中,又或者您更喜歡 VARCHAR2 的簡(jiǎn)便性,則可以考慮使用 VARCHAR2 字段。VARCHAR2 值最多可容納 32K個(gè)(原文是32,不對(duì))字節(jié)。
工作負(fù)載類(lèi)型和數(shù)據(jù)訪問(wèn)模式
數(shù)據(jù)庫(kù)工作負(fù)載可分為操作型工作負(fù)載和分析型工作負(fù)載。操作型工作負(fù)載也稱(chēng)為聯(lián)機(jī)事務(wù)處理系統(tǒng) (OLTP),它們以事務(wù)為導(dǎo)向,擁有眾多用戶,并且旨在實(shí)現(xiàn)即時(shí)響應(yīng);例如,銀行的自動(dòng)柜員機(jī) (ATM)。OLTP 系統(tǒng)支持所有數(shù)據(jù)操作類(lèi)型。典型的操作涉及使用最少行數(shù)插入或更新數(shù)據(jù)的事務(wù)。OLTP 系統(tǒng)的性能目標(biāo)是事務(wù)速度、吞吐量和數(shù)據(jù)庫(kù)并發(fā)性。相比之下,分析型工作負(fù)載(例如聯(lián)機(jī)分析處理 (OLAP)、數(shù)據(jù)倉(cāng)庫(kù)和數(shù)據(jù)湖)專(zhuān)為數(shù)據(jù)分析而構(gòu)建,用戶較少,并且旨在處理大量數(shù)據(jù)。典型的操作包括使用復(fù)雜的資源密集型查詢處理數(shù)千或數(shù)百萬(wàn)行數(shù)據(jù),這些查詢會(huì)連接和聚合多個(gè)表之間的數(shù)據(jù)。OLAP 系統(tǒng)針對(duì)查詢進(jìn)行了優(yōu)化。
按鍵檢索 JSON 文檔 (OLTP)
您的工作負(fù)載會(huì)根據(jù)關(guān)系列(鍵)選擇單個(gè) JSON 文檔,并將 JSON 數(shù)據(jù)存儲(chǔ)在第二個(gè)(負(fù)載)列(可以認(rèn)為是key/value中的value)中。鍵列上的主鍵約束強(qiáng)制鍵值唯一,并為其創(chuàng)建索引以便快速查找。如果鍵不是隨機(jī)的(例如,使用序列或標(biāo)識(shí)列),則索引可能會(huì)成為高事務(wù)性系統(tǒng)中的熱點(diǎn),因?yàn)椴l(fā)/后續(xù)插入會(huì)命中同一個(gè)索引塊?;阪I列對(duì)索引進(jìn)行哈希分區(qū)(常見(jiàn)的分散熱點(diǎn)的做法)會(huì)將插入操作均勻分布到所有分區(qū)。SODA 和 MongoDB 集合自動(dòng)具有主鍵列——基于鍵的文檔查找無(wú)需進(jìn)一步操作。
按字段值檢索 JSON 文檔 (OLTP)
在這里,通過(guò) JSON 文檔中的字段值選擇一個(gè)或幾個(gè)文檔。JSON_VALUE 或 JSON_EXISTS 運(yùn)算符中的路徑表達(dá)式定義了這些值。如果重復(fù)使用相同的路徑表達(dá)式,建議使用 JSON_VALUE 的基于函數(shù)的索引。對(duì)感興趣的字段值進(jìn)行索引,可以將數(shù)據(jù)檢索的全表掃描替換為索引查找,從而確保最佳性能。
雖然在 JSON 文檔中索引單個(gè)字段很容易,但數(shù)組索引卻更具挑戰(zhàn)性?;诤瘮?shù)的索引無(wú)法索引數(shù)組值(函數(shù)每個(gè) JSON 數(shù)據(jù)只能返回一個(gè)值);在 Oracle 21c 之前的版本中,可以使用物化視圖作為替代方案:物化視圖將數(shù)組擴(kuò)展為具有多個(gè)行條目的關(guān)系列,然后將其作為普通列進(jìn)行索引。Oracle 全面的查詢重寫(xiě)框架會(huì)自動(dòng)重寫(xiě)針對(duì) JSON 文檔的 SQL 語(yǔ)句,以便使用物化視圖進(jìn)行快速數(shù)據(jù)檢索。在 Oracle 21c 中,您可以使用此版本中引入的全新多值索引功能,原生地為 JSON 數(shù)組中的值創(chuàng)建索引。
使用全文搜索檢索 JSON 文檔 (OLTP、OLAP)
某些工作負(fù)載僅知道感興趣的值,而不知道 JSON 文檔中字段的路徑表達(dá)式,例如對(duì)任意文檔的臨時(shí)查詢。Oracle 提供了 JSON 搜索索引來(lái)提升此類(lèi)工作負(fù)載的性能。借助 JSON 搜索索引,SQL/JSON 運(yùn)算符 JSON_TEXTCONTAINS 允許根據(jù)文本搜索條件(包括詞干提取和模糊搜索)選擇行。
提取 JSON 值用于報(bào)告或分析 (OLAP)
在報(bào)告或分析用例中,JSON 數(shù)據(jù)會(huì)映射到關(guān)系模型,以便使用 SQL 進(jìn)行進(jìn)一步處理。常用的 SQL 操作包括連接(與其他 JSON 或關(guān)系數(shù)據(jù))、聚合(求和、求平均值、窗口函數(shù))或機(jī)器學(xué)習(xí)(分類(lèi)、預(yù)測(cè))。SQL/JSON 運(yùn)算符 JSON_TABLE 允許從 JSON 映射到關(guān)系模型。Oracle 數(shù)據(jù)庫(kù)會(huì)盡可能將多個(gè) JSON 查詢運(yùn)算符優(yōu)化為單個(gè) JSON_TABLE 語(yǔ)句(顯示在查詢執(zhí)行計(jì)劃中)。
對(duì)于高選擇性分析(根據(jù)字段過(guò)濾條件僅選擇少量 JSON 文檔),可以使用索引優(yōu)化訪問(wèn)。如果訪問(wèn)的行數(shù)較多(但并非全部),且索引的選擇性不再足夠,則應(yīng)考慮對(duì)數(shù)據(jù)進(jìn)行分區(qū),以從查詢中剔除不相關(guān)的分區(qū)。此外,處理大數(shù)據(jù)量時(shí),建議充分利用并行執(zhí)行。SQL/JSON 運(yùn)算符 JSON_TABLE 可以并行化,且沒(méi)有任何限制。(三個(gè)優(yōu)化手段:索引,分區(qū),并行)
假設(shè)您反復(fù)運(yùn)行相同的 JSON 到關(guān)系型數(shù)據(jù)庫(kù)轉(zhuǎn)換,例如每日?qǐng)?bào)告或儀表板查詢。在這種情況下,物化視圖通過(guò)在視圖中物化中間結(jié)果,可以完全避免在運(yùn)行時(shí)重復(fù)執(zhí)行相同的 JSON_TABLE 轉(zhuǎn)換。JSON_TABLE 物化視圖支持快速刷新,因此在插入或更新后能夠高效自動(dòng)地刷新。物化視圖還可以與 Oracle Database In-Memory 結(jié)合使用,以受益于內(nèi)存列壓縮和快速 SIMD 掃描。這可以顯著提升性能,尤其是對(duì)于分析查詢而言。(物化視圖(主)+ In-Memory(輔)優(yōu)化)
JSON 生成 (OLTP、OLAP)
Oracle 數(shù)據(jù)庫(kù)新增了 SQL/JSON 運(yùn)算符,(可能指的是JSON_ARRAY和JSON_OBJECT)用于從關(guān)系數(shù)據(jù)和查詢結(jié)果生成新的 JSON 數(shù)據(jù)。典型的用例是修改某個(gè) JSON 文檔的結(jié)構(gòu),或?qū)⒎治霾樵兊慕Y(jié)果作為 JSON 數(shù)據(jù)提取返回。當(dāng)僅訪問(wèn)少量行時(shí),索引可以提供快速訪問(wèn)。如果 JSON 生成基于多行數(shù)據(jù),則應(yīng)考慮使用物化視圖,但需要注意的是,JSON 生成的快速刷新功能僅在有限情況下才支持。
性能特性和技術(shù) – 深入探討
以下部分將更詳細(xì)地介紹與性能相關(guān)的功能,并附上示例。通常,常規(guī)的 SQL 調(diào)優(yōu)技巧是適用的:您可以利用已有的技能。這縮短了學(xué)習(xí)曲線,并消除了 DBA 和數(shù)據(jù)庫(kù)管理員對(duì)在 Oracle 數(shù)據(jù)庫(kù)中采用 JSON 的擔(dān)憂。這些調(diào)優(yōu)技巧背后的主要理念是減少需要讀取和處理的數(shù)據(jù)量:
基于函數(shù)的索引
基于函數(shù)的索引可以基于特定鍵或鍵組合創(chuàng)建,并優(yōu)化使用 SQL/JSON 運(yùn)算符對(duì)相同鍵進(jìn)行的查詢操作?;诤瘮?shù)的索引使用 JSON_VALUE 運(yùn)算符構(gòu)建,并支持位圖和 B 樹(shù)索引格式。
以下示例在示例 JSON 文檔的 PONumber 鍵上創(chuàng)建了一個(gè)(唯一的)函數(shù)索引,該索引可通過(guò)路徑表達(dá)式“$.PONumber”訪問(wèn)。本示例假設(shè) JSON 數(shù)據(jù)存儲(chǔ)在名為“purchaseorder”的表的“data”列中。
create unique index PO_NUMBER_IDX on PURCHASEORDER po( json_value(po.DATA, '$.PONumber' returning number null on empty error on error));
PONumber 值將被提?。ú⒕幦胨饕閿?shù)字。這會(huì)影響范圍查詢(按數(shù)字排序而非字母排序),并避免在運(yùn)行時(shí)進(jìn)行數(shù)學(xué)運(yùn)算或比較的數(shù)據(jù)類(lèi)型轉(zhuǎn)換。缺失值將被編入索引,作為 SQL NULL 值。
以下查詢使用了簡(jiǎn)化的 JSON 語(yǔ)法。由于使用了 number() 項(xiàng)方法,因此將使用索引進(jìn)行數(shù)據(jù)檢索,如計(jì)劃所示。
select data from PURCHASEORDER po where po.data.PONumber.number() = 200; ----------------------------------------------------- | Id | Operation | Name | ----------------------------------------------------- | 0 | SELECT STATEMENT | | | 1 | TABLE ACCESS BY INDEX ROWID| PURCHASEORDER | |* 2 | INDEX UNIQUE SCAN | PO_NUMBER_IDX | -----------------------------------------------------
多值索引
如果路徑表達(dá)式可以選擇多個(gè)值,則建議使用多值索引——這在訪問(wèn) JSON 數(shù)組中的值時(shí)很常見(jiàn)。以下代碼在示例 JSON 文檔的 JSON 數(shù)組“LineItems”中的字段“UPCCode”上創(chuàng)建了多值索引。這些值以字符串形式進(jìn)行索引。
create multivalue index UPCCODE_INDEX on PURCHASEORDER po ( po.data.LineItems.Part.UPCCode.string());
多值索引也使用 B 樹(shù),但由于生成的 ROWID 需要去重,因此速度比函數(shù)索引略慢。因此,如果已知路徑表達(dá)式最多返回一個(gè)值,則應(yīng)優(yōu)先使用基于函數(shù)的索引。多值索引是在 Oracle 21c 中引入的(出于早期的原因,可以使用物化視圖來(lái)加速對(duì)數(shù)組的訪問(wèn))。
以下查詢使用了多值索引:
select data from PURCHASEORDER po where po.data.LineItems.Part.UPCCode.string() = '13131092705'; ------------------------------------------------------------- | Id | Operation | Name | | 0 | SELECT STATEMENT | | |* 1 | TABLE ACCESS BY INDEX ROWID BATCHED | PURCHASEORDER | |* 2 | INDEX RANGE SCAN (MULTI VALUE) | UPCCODE_INDEX | -------------------------------------------------------------
JSON 搜索索引
Oracle 數(shù)據(jù)庫(kù)支持使用基于 Oracle 全文索引的搜索索引來(lái)索引整個(gè) JSON 文檔。該搜索索引不僅包含所有值,還包含其字段名稱(chēng),并允許進(jìn)行全文搜索。以下示例在“purchaseorder”上創(chuàng)建了一個(gè) JSON 搜索索引。
create search index PO_FULL_IDX on PURCHASEORDER po (po.data) for json parameters('SYNC (EVERY "FREQ=SECONDLY; INTERVAL=1") DATAGUIDE OFF');
“parameters”子句指定索引是異步的,每秒同步一次。也可以在每次事務(wù)提交時(shí)同步索引,但這會(huì)增加索引維護(hù)成本并降低并發(fā) DML 的吞吐量。JSON 搜索索引還可以通過(guò)名為 JSON Dataguide 的功能在 DML 操作期間發(fā)現(xiàn)模式更改——例如,它允許自動(dòng)生成 JSON_Table 視圖。“DATAGUIDE OFF”子句禁用此模式發(fā)現(xiàn)功能,從而降低 JSON 搜索索引在 DML 操作期間的成本。
JSON 搜索索引的底層數(shù)據(jù)結(jié)構(gòu)是發(fā)布列表,通常比 B 樹(shù)索引慢。如果 JSON 搜索索引與基于函數(shù)的索引或多值索引一起使用,則優(yōu)化器會(huì)盡可能優(yōu)先選擇這些索引。由于 JSON 搜索索引會(huì)索引整個(gè) JSON 數(shù)據(jù),因此其大小將顯著大于其他索引,通常在原始數(shù)據(jù)的 20%-30% 左右。JSON 搜索索引支持 JSON 數(shù)組中的值以及全文搜索操作。以下示例選擇所有“Description”字段同時(shí)包含單詞“Magic”和“Christmas”的文檔。除了“{and}”,還可以使用“{near}”或“{not(…)}”。有關(guān) JSON 搜索索引功能的更多信息,請(qǐng)參閱文檔
select data from PURCHASEORDER po where JSON_TEXTCONTAINS(po.data, '$.LineItems.Part.Description', 'Magic {and} Christmas');
查詢執(zhí)行計(jì)劃將 JSON 搜索索引顯示為“域索引”:
--------------------------------------------------------- | Id | Operation | Name | --------------------------------------------------------- | 0 | SELECT STATEMENT | | | 1 | TABLE ACCESS BY INDEX ROWID | PURCHASEORDER | |* 2 | DOMAIN INDEX | PO_FULL_IDX | ---------------------------------------------------------
對(duì)于包含大量 DML 操作的工作負(fù)載,使用單個(gè) JSON 搜索索引來(lái)替代大量的函數(shù)索引和多值索引可能會(huì)有所幫助,從而減少索引維護(hù)量(DML 操作后的索引同步)。更多優(yōu)化策略請(qǐng)參閱右側(cè)引用的博客。
物化視圖
您可以使用物化視圖來(lái)提升頻繁訪問(wèn)多行的查詢(而非基于索引驅(qū)動(dòng)的鍵值查找)的性能。物化視圖會(huì)持久保存查詢結(jié)果。部分或完全匹配物化視圖查詢的后續(xù)查詢無(wú)需重新運(yùn)行原始查詢即可訪問(wèn)物化數(shù)據(jù)(以空間換取速度)。
在本文檔中,我們主要關(guān)注 JSON_TABLE 物化視圖。以下代碼將創(chuàng)建一個(gè)物化視圖,其中包含示例 JSON 文檔中“LineItems”數(shù)組的值。如前所述,使用物化視圖可以在 Oracle 19c 中索引 JSON 數(shù)組值,因?yàn)樵摪姹静恢С侄嘀?JSON 索引。
create materialized view PO_MV build immediate refresh fast on statement with primary key as select po.id, jt.* from PURCHASEORDER po, json_table(po.data, '$' error on error null on empty columns ( po_number NUMBER PATH '$.PONumber', userid VARCHAR2(10) PATH '$.User', NESTED PATH '$.LineItems[*]' columns ( itemno NUMBER PATH '$.ItemNumber', description VARCHAR2(256) PATH '$.Part.Description', upc_code NUMBER PATH '$.Part.UPCCode', quantity NUMBER PATH '$.Quantity', unitprice NUMBER PATH '$.Part.UnitPrice'))) jt;
在我們的物化視圖中將數(shù)組值轉(zhuǎn)換為多行,使我們能夠在 JSON 數(shù)組的字段上創(chuàng)建附加(輔助)索引,如下所示:
CREATE INDEX mv_idx ON PO_MV(upc_code, quantity);
現(xiàn)在,基表上的 SQL/JSON 查詢將透明地重寫(xiě),以盡可能使用物化視圖及其索引。以下查詢是一個(gè)示例,其中 Oracle 自動(dòng)重寫(xiě)查詢以使用物化視圖及其二級(jí)索引,如執(zhí)行計(jì)劃中所示:
select data from PURCHASEORDER po where JSON_EXISTS(po.data, '$.LineItems[*]?(@.Part.UPCCode == 1234)'); ----------------------------------------------------------------- | Id | Operation | Name | … | 4 | MAT_VIEW ACCESS BY INDEX ROWID BATCHED| PO_MV | |* 5 | INDEX RANGE SCAN | MV_IDX | -----------------------------------------------------------------
為了使物化視圖 (MV) 與底層數(shù)據(jù)(DML 操作后)保持同步,我們將物化視圖設(shè)置為“語(yǔ)句快速刷新”。這可以自動(dòng)執(zhí)行刷新過(guò)程,并始終保持物化視圖和基表數(shù)據(jù)一致。本文不深入討論物化視圖的各種刷新機(jī)制。更多詳細(xì)信息,請(qǐng)參閱相關(guān)文檔。
Oracle 分區(qū)
您可以像平常一樣對(duì)包含文檔的表進(jìn)行分區(qū),以提高性能:分區(qū)可以將表和索引細(xì)分為單獨(dú)的較小物理對(duì)象,即所謂的分區(qū)。**分區(qū)表中的數(shù)據(jù)位置由分區(qū)鍵標(biāo)識(shí)。此鍵可以是關(guān)系列,也可以是 JSON 數(shù)據(jù)中的字段。**從應(yīng)用程序的角度來(lái)看,分區(qū)表與非分區(qū)表完全相同。
以下示例創(chuàng)建一個(gè)范圍分區(qū)表,其分區(qū)鍵從存儲(chǔ)在“data”列中的 JSON 文檔中提取,并使用基于 JSON_VALUE 的虛擬列“po_num_vc”;
CREATE TABLE part_j (id VARCHAR2 (32) NOT NULL PRIMARY KEY, data JSON, po_num_vc NUMBER GENERATED ALWAYS AS (json_value (data, '$.PONumber' RETURNING NUMBER))) PARTITION BY RANGE (po_num_vc) (PARTITION p1 VALUES LESS THAN (1000), PARTITION p2 VALUES LESS THAN (2000));
對(duì) JSON 字段“$.PONumber”(用作虛擬列分區(qū)鍵的 JSON 字段)進(jìn)行過(guò)濾的查詢將明顯受益于 Oracle 分區(qū)功能:一種稱(chēng)為分區(qū)修剪的優(yōu)化技術(shù)會(huì)自動(dòng)排除所有不相關(guān)的分區(qū),即已知不包含任何與查詢相關(guān)的數(shù)據(jù)的分區(qū)。
以下示例查詢只需訪問(wèn)第一個(gè)分區(qū),因?yàn)椴樵兊南嗟戎^詞只能在此分區(qū)中找到匹配的記錄。執(zhí)行計(jì)劃中顯示了這一點(diǎn),其中 Pstart 列和 Pstop 列均為 1。
select data from part_j where json_value (data, '$.PONumber' RETURNING NUMBER) = 500; ----------------------------------------------------------------- | Id | Operation | Name | Time | Pstart| Pstop | ----------------------------------------------------------------- | 0 | SELECT STATEMENT | | 00:00:01 | | | | 1 | PARTITION RANGE ALL | | 00:00:01 | 1 | 1 | |* 2 | TABLE ACCESS FULL | PART_J | 00:00:01 | 1 | 1 | -----------------------------------------------------------------
Oracle 分區(qū)有多種機(jī)制來(lái)對(duì)表進(jìn)行分區(qū),由于篇幅原因,這里不再贅述。更多詳情請(qǐng)參閱文檔。通常,對(duì)于較大的 JSON 文檔(平均 > 32kb),使用關(guān)系列作為分區(qū)鍵在 DML 操作期間通常比使用 JSON_VALUE 虛擬列性能更高,因?yàn)楹笳咝枰趯?xiě)入正確分區(qū)之前從 JSON 中提取分區(qū)鍵。
并行執(zhí)行
通過(guò)使用多個(gè)進(jìn)程處理 JSON 文檔,可以并行化 JSON 操作(例如查詢或批量更新)。這可以更高效地利用硬件資源,是大規(guī)模數(shù)據(jù)處理的關(guān)鍵。
大型數(shù)據(jù)倉(cāng)庫(kù)應(yīng)始終使用并行執(zhí)行來(lái)實(shí)現(xiàn)良好的性能。OLTP 應(yīng)用程序中的特定操作(例如批處理操作)也可以從并行執(zhí)行中顯著受益。
并行執(zhí)行支持查詢和 DML(插入、更新)。有多種方法可以啟用和配置并行執(zhí)行。例如,Oracle 自治數(shù)據(jù)庫(kù)會(huì)根據(jù)為連接選擇的消費(fèi)者組自動(dòng)選擇并行度。對(duì)于手動(dòng)控制并行度的數(shù)據(jù)庫(kù),您可以在會(huì)話級(jí)別啟用并行度或裝飾單個(gè)對(duì)象。例如,以下代碼為我們的表“purchaseorder”啟用了 8 級(jí)并行度。
alter table PURCHASEORDER parallel 8;
如果使用并行執(zhí)行,則執(zhí)行計(jì)劃將顯示帶有“PX”的行。
| 1 | PX COORDINATOR || 2 | PX SEND QC (ORDER)|
Oracle 內(nèi)存列式存儲(chǔ)
JSON 數(shù)據(jù)可以存儲(chǔ)在內(nèi)存列存儲(chǔ)(IM 列存儲(chǔ))中,從而提升查詢性能。最大可達(dá) 32 KB 的 JSON 值可以與其他關(guān)系列一起直接加載并在內(nèi)存中處理。通常,JSON 文檔中的值并非都與分析查詢相關(guān)。在這種情況下,只需在內(nèi)存中分別移動(dòng)相關(guān)的 JSON 字段即可更高效地利用內(nèi)存:可以使用虛擬列或中間物化視圖。
以下示例向表“purchaseorder”添加了一個(gè)虛擬列,該列用于從訂單地址中提取“zipCode”字段。虛擬列已添加,并且表已啟用內(nèi)存處理。
alter table PURCHASEORDER add (ZIP varchar2(4000) generated always as (JSON_VALUE(data, '$.ShippingInstructions.Address.zipCode.number()'))); alter table PURCHASEORDER inmemory;
以下分析示例查詢按 zipCode 計(jì)算訂單數(shù)量,并利用快速內(nèi)存??處理,如執(zhí)行計(jì)劃所示。
select zip, count(1) from PURCHASEORDER group by zip ; ----------------------------------------------------- | Id | Operation | Name | ----------------------------------------------------- | 0 | SELECT STATEMENT | | | 1 | HASH GROUP BY | | | 2 | TABLE ACCESS INMEMORY FULL| PURCHASEORDER | -----------------------------------------------------
Oracle Exadata 數(shù)據(jù)庫(kù)云服務(wù)器
Exadata 加速 JSON 性能:包含表和索引掃描的查詢可以將數(shù)據(jù)搜索和檢索處理卸載到 Exadata 存儲(chǔ)服務(wù)器。對(duì)于 JSON 運(yùn)算符(例如,在查詢的 WHERE 子句中使用 JSON_VALUE 或 JSON_EXISTS),此卸載操作會(huì)自動(dòng)且透明地進(jìn)行。最大 4KB 的 JSON 文檔可以卸載到 Exadata 存儲(chǔ)服務(wù)器。更大的文檔將在數(shù)據(jù)庫(kù)中處理。
執(zhí)行計(jì)劃中的 STORAGE 術(shù)語(yǔ)表明卸載已完成:
----------------------------------------------------- | Id | Operation | Name | ----------------------------------------------------- |* 3 | TABLE ACCESS STORAGE FULL| PURCHASEORDER | -----------------------------------------------------
Oracle 真正應(yīng)用集群
Oracle 真正應(yīng)用集群 (RAC) 允許客戶在多臺(tái)服務(wù)器上運(yùn)行單個(gè) Oracle 數(shù)據(jù)庫(kù),以最大限度地提高可用性并在訪問(wèn)共享存儲(chǔ)時(shí)實(shí)現(xiàn)水平可擴(kuò)展性。
使用 Oracle Real Application Clusters 對(duì)于 JSON 文檔的處理是透明的,并且任何 SQL/JSON 處理都會(huì)自動(dòng)受益。
Oracle 分片
Oracle 分片也是一種水平擴(kuò)展技術(shù),但與 RAC 不同,它采用無(wú)共享架構(gòu)。分片技術(shù)允許 JSON 文檔擴(kuò)展到海量數(shù)據(jù)和事務(wù)處理,并支持?jǐn)?shù)據(jù)主權(quán)。JSON 文檔根據(jù)分片鍵(可以是關(guān)系列或 JSON 字段)分發(fā)到各個(gè)數(shù)據(jù)庫(kù)表分片中。
使用 Oracle 分片技術(shù)對(duì)于分片 JSON 文檔的處理是透明的。對(duì)于許多操作而言,分片文檔的處理僅在擁有特定分片的數(shù)據(jù)庫(kù)上進(jìn)行,而跨分片查詢將透明地收集并聚合來(lái)自所有相關(guān)分片的結(jié)果數(shù)據(jù)。
Oracle 數(shù)據(jù)庫(kù)中 JSON 性能調(diào)優(yōu)特性到此結(jié)束。以下總結(jié)了 JSON 文檔存儲(chǔ) API(MongoDB 集合和 SODA 集合)的性能相關(guān)主題:
性能技巧SODA 系列
Oracle 數(shù)據(jù)庫(kù)提供允許以集合形式訪問(wèn) JSON 數(shù)據(jù)的 API:適用于 MongoDB 的 Oracle 數(shù)據(jù)庫(kù) API 和簡(jiǎn)單 Oracle 文檔訪問(wèn) API -SODA。從概念上講,JSON 集合將 JSON 數(shù)據(jù)(稱(chēng)為文檔)存儲(chǔ)在自動(dòng)生成的表中(以便也可以通過(guò) SQL 訪問(wèn))。SODA 支持與包含 JSON 數(shù)據(jù)的常規(guī)表相同的存儲(chǔ)選項(xiàng),并且適用相同的建議:在 Oracle 19c 上使用 BLOB,在 Oracle 21c 上使用原生 JSON 類(lèi)型。
用戶通常使用原生語(yǔ)言驅(qū)動(dòng)程序(例如,Java 版 SODA 或 Python 版 SODA)處理 JSON 集合。SODA 原生語(yǔ)言驅(qū)動(dòng)程序通常比 REST 驅(qū)動(dòng)程序(REST 版 SODA)提供更高的吞吐量(每秒操作數(shù))。
建議按如下方式配置 SODA 驅(qū)動(dòng)程序:
- 啟用 SODA 元數(shù)據(jù)緩存
SODA 驅(qū)動(dòng)程序需要了解每個(gè) JSON 集合的元數(shù)據(jù)(列名、類(lèi)型等)。啟用元數(shù)據(jù)緩存可以減少與數(shù)據(jù)庫(kù)的往返次數(shù),從而提高延遲和吞吐量。
- 啟用語(yǔ)句緩存
語(yǔ)句緩存通過(guò)緩存重復(fù)使用的可執(zhí)行語(yǔ)句(例??如在循環(huán)中或在重復(fù)調(diào)用的方法中)來(lái)提高性能。對(duì)于 Java,語(yǔ)句緩存是使用 JDBC 啟用的。
- 對(duì)于負(fù)載平衡系統(tǒng):關(guān)閉 DNS 緩存
負(fù)載平衡允許將 SODA 操作分布到不同的節(jié)點(diǎn)。如果啟用了 DNS 緩存,則所有連接都可能使用同一節(jié)點(diǎn),從而導(dǎo)致負(fù)載平衡失效。對(duì)于 Java,應(yīng)設(shè)置以下系統(tǒng)屬性:inet.addr.ttl=0
數(shù)據(jù)庫(kù)性能調(diào)優(yōu)技術(shù)也適用于 SODA:例如,SODA 集合可以分區(qū)或分片,并且可以使用索引和/或物化視圖加速查詢。SODA 操作會(huì)自動(dòng)轉(zhuǎn)換為等效的 SQL 操作:例如,SODA 查詢將轉(zhuǎn)換為在 WHERE 子句中使用 JSON_EXISTS 運(yùn)算符的 SELECT 語(yǔ)句。
可以從 v$sql 數(shù)據(jù)庫(kù)視圖中檢索 SQL 操作,也可以通過(guò)直接在 SODA 驅(qū)動(dòng)程序中啟用日志記錄來(lái)檢索 SQL 操作:在 Java 中,使用標(biāo)準(zhǔn)日志記錄包 - 可以為 SODA 啟用它,如下所示:
java -classpath "..." -Doracle.soda.trace=true -Djava.util.logging.config.file=logging.properties <program>
- ‘oracle.soda.trace=true’ 啟用 SQL 語(yǔ)句的日志記錄。
- ‘logging.java.util.logging.config.file’ 定義 java.util.logging 配置文件的路徑,該文件允許不同的日志記錄級(jí)別:FINEST 是最詳細(xì)的日志記錄級(jí)別。
更多信息 – 鏈接
- Oracle XE
- Oracle Standard Edition
- Oracle Enterprise Edition
- Oracle Exadata Cloud Service
- Oracle Exadata Cloud at Customer
- Oracle Exadata Database Machine
- Oracle Database Cloud Service
- Oracle Autonomous JSON
- Oracle Autonomous Transaction Processing
- Oracle Autonomous Data Warehouse
到此這篇關(guān)于Oracle 數(shù)據(jù)庫(kù)中的 JSON性能注意事項(xiàng)(最佳實(shí)踐)的文章就介紹到這了,更多相關(guān)Oracle 數(shù)據(jù)庫(kù)JSON內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
在Spring中用select last_insert_id()時(shí)遇到問(wèn)題
一直使用的Oracle數(shù)據(jù)庫(kù),通過(guò)序列來(lái)實(shí)現(xiàn)自增字段,插入之前就已經(jīng)獲得了自增id,保存下來(lái)即可在后來(lái)的操作中使用2009-05-05oracle如何恢復(fù)被覆蓋的存儲(chǔ)過(guò)程
如果你不小心覆蓋了之前的存儲(chǔ)過(guò)程,那得趕緊閃回,時(shí)長(zhǎng)越長(zhǎng)閃回的可能性越小,下面為大家介紹下恢復(fù)原理2014-05-05Oracle回滾段的概念,用法和規(guī)劃及問(wèn)題的解決
Oracle回滾段的概念,用法和規(guī)劃及問(wèn)題的解決...2007-03-03navicat使用Oracle創(chuàng)建庫(kù)以及用戶超詳細(xì)教程
本文介紹如何使用Navicat連接Oracle數(shù)據(jù)庫(kù),步驟包括準(zhǔn)備工作、新建連接、輸入用戶名和密碼、測(cè)試連接、建立庫(kù)和用戶、授權(quán)以及測(cè)試的相關(guān)資料,需要的朋友可以參考下2024-09-09Oracle WebLogic Server 12.2.1.2安裝部署教程
這篇文章主要介紹了Oracle WebLogic Server 12.2.1.2安裝部署教程,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-12-12