详细信息:Oracle 数据库 12c,数据库版本:12.1.0.2.0
问题描述及要求:
第1部分 :
- 我将 JSON 数据存储在 NCLOB 列中。
- 我需要从 JSON 数据中搜索文本。
- 考虑到性能,我可以选择使用数据类型 BLOB,因为数据是 JSON 并且在 BLOB 列中。我可以使用 JSON 索引全文搜索。
与 NCLOB 上的简单查询 (LIKE) 相比,在 BLOB 列上使用 JSON 文本搜索索引进行搜索时,性能显着提高,因此使用 BLOB 列。
关于 JSON 搜索索引:
JSON 搜索索引是一种专门针对 JSON 数据的全文索引。优化器仅在数据库使用AL32UTF8 或 WE8ISO8859P1 字符集时才考虑使用索引,并且仅适用于 VARCHAR2、BLOB 或 CLOB 列中的 JSON 数据,而不是 NVARCHAR2 和 NCLOB 列。
第2部分 :
我们有两种数据库类型,即单字节和多字节部署
单字节字符集:
NLS_NCHAR_CHARACTERSET--->AL16UTF16, NLS_CHARACTERSET------>WE8MSWIN1252
多字节字符集:
NLS_NCHAR_CHARACTERSET--->AL16UTF16, NLS_CHARACTERSET------>AL32UTF8
第 3 部分:
在多字节部署中,我能够存储和搜索(使用 JSON_TEXTCONTAINS)多字节文本,例如 'məharaːʂʈrə'。原因:因为数据库使用 AL32UTF8(BLOB 列)字符集 注意:JSON_TEXTCONTAINS 仅适用于索引。
在单字节部署中,我无法存储相同的文本,即 'məharaːʂʈrə'(由于它是多字节的,转换会导致数据丢失,例如 'm?hara???r?')
问题:如何在具有字符集的单字节部署的BLOB列中存储多字节数据,即'məharaːʂʈrə':WE8MSWIN1252。
如 oracle 所述:如果数据库使用AL32UTF8 或 WE8ISO8859P1 字符集,优化器只会考虑使用索引 请注意,我也可以在单字节环境中使用 JSON 搜索索引,即 JSON_TEXTCONTAINS(对于简单搜索,即单字节)。
一旦我能够按原样存储数据,我将能够使用 JSON_TEXTCONTAINS 进行搜索。
示例代码(在单字节和多字节部署中尝试:请注意:https ://livesql.oracle.com/是多字节部署。
创建表:
create table departments_json (
department_id integer not null primary key,
department_data blob not null
);
数据应该是严格的 Json(所以我们可以用点符号遍历):
alter table departments_json
add constraint dept_data_json
check ( department_data is JSON FORMAT JSON STRICT );
创建索引:
create index deptj_ctx_ix
on departments_json (department_data)
indextype is ctxsys.context parameters ('section group CTXSYS.JSON_SECTION_GROUP sync (on commit)');
插入简单的json
insert into departments_json
values ( 140, utl_raw.cast_to_raw ('{"department_list":[{"Deptname":"DEPT-A", "value" : "məharaːʂʈrə"}]}'));
如果有任何错误(单字节),请将其转换:
insert into departments_json
values ( 140, UTL_RAW.convert(utl_raw.cast_to_raw ('{"department_list":[{"Deptname":"DEPT-A", "value" : "məharaːʂʈrə"}]}'),'AL32UTF8','WE8MSWIN1252'));
存储值:
SELECT json_value(department_data format json, '$.department_list.value' ) FROM departments_json JS WHERE DEPARTMENT_ID=140;
观察:在单字节环境下会导致数据丢失。
现在搜索:
SELECT *
FROM departments_json
WHERE JSON_TEXTCONTAINS(department_data, '$.department_list.value', 'məharaːʂʈrə');
观察:多字节将产生行,但单字节将不会产生行。
也能够在单字节环境中使用 JSON 搜索索引,即 JSON_TEXTCONTAINS(对于简单搜索,即单字节)——下面的查询结果为一行:
SELECT *
FROM departments_json
WHERE JSON_TEXTCONTAINS(department_data, '$.department_list.Deptname', 'DEPT-A');