

其实在我做的平台的“史前版本”也是尝试适配过一些国内走的比较靠前的数据库,由于没有图功能,只能通过对标属性图的表设计加上SQL定义/视图来实现类似功能,但问题也接踵而至:
光是这两点让我暂时停下了国产数据库的适配脚步,但是上周一位国产数据库架构师悄咪咪找到我,说他们新版本即将发布,完全满足我对数据库能力的需求,下周就能发版给到我。这不,这周我就拿到了YashanDB 23.5.4.100的内测版本!(测试结果让人非常惊讶!)
崖山数据库其实是大家的老朋友了,但是在本次23.5.4.100中有一个特别的描述:

https://doc.yashandb.com/yashandb/23.5/zh/All-Manuals/Product-Overview/Release-Notes/23.5.4.html
因此,YashanDB(崖山数据库)是深圳崖山科技有限公司自主研发的国产数据库管理系统,版本23.5.4.100(本文涉及为内测版)。区别于传统关系型数据库,YashanDB将向量的语义检索、图的路径推理、全文倒排索引、空间地理分析、JSON半结构化处理、非结构化文件管理等能力统一集成到数据库内核中,实现"一套存储引擎、一套MVCC与WAL、统一查询优化器"的架构范式。
特性 | 说明 |
|---|---|
统一存储 | 所有模态共享同一套存储引擎,无数据复制 |
事务一致性 | 向量、图、全文、JSON、关系表共享MVCC,ACID保证 |
统一优化器 | 一条 SQL 同时跨越多种模态,优化器统一规划执行计划 |
零ETL | 图基于关系表实时映射,底层INSERT/UPDATE/DELETE实时反映,无需物化刷新 |
内核原生 | 向量、图、全文、空间等能力内置于内核,无需安装外部扩展 |
本次测试覆盖 YashanDB 全部多模新特性,共 7 大类 44 个测试用例:
模态 | 说明 | 测试用例数 |
|---|---|---|
模态1: 向量能力 | VECTOR 数据类型、HNSW 索引、KNN/ANN 检索、多种距离度量 | 8 |
模态2: 图能力 | SQL/PGQ 属性图、GRAPH_TABLE 查询、多跳路径 | 5 |
模态3: 文档/JSON | JSON 类型、JSON_VALUE/QUERY/EXISTS、JSON_ARRAY_GET 深度探索 | 6 |
模态4: 非结构化文件管理 | DBMS_FS 卷管理、目录/文件 CRUD、READ/LISTDIR/EXIST | 7 |
模态5: 全文检索 | SEARCH INDEX、CONTAINS 检索、布尔组合、向量+全文融合表 | 6 |
模态6: 空间能力 | ST_GEOMETRY、R-Tree 索引、坐标系转换、距离计算 | 4 |
跨模态融合 | 全文+向量 UNION、向量视图+属性图、关系过滤+向量排序 | 5 |
JSON_ARRAY_GET 探索 | 类型转换、接口差异、最佳实践 | 3 (子测试) |
功能概述: YashanDB提供原生VECTOR(n)数据类型,支持FLOAT32/FLOAT64精度,最大65535维。支持HNSW索引加速近似检索,三种距离度量: EUCLIDEAN、COSINE、DOT。
参考文档: https://doc.yashandb.com/yashandb/23.5.4/zh/All-Manuals/Reference-Manual-of-Vector-Data/About-Vector.html
CREATETABLE docs (
id BIGINT PRIMARY KEY,
title VARCHAR(200),
content CLOB,
embedding VECTOR(3)
);

支持两种插入方式: 字符串转换和AI_EMBED函数生成。
-- 方式一: 通过TO_VECTOR字符串转换
INSERT INTO docs VALUES
(1, '多模数据库入门', '本文介绍原生多模数据库的技术路线与产品演进', TO_VECTOR('[0.12,0.88,0.34]')),
(2, 'AI时代的数据库', '探讨大模型时代数据库需要具备的新能力', TO_VECTOR('[0.21,0.65,0.77]')),
(3, '传统SQL优化技巧', '索引、代价模型与执行计划调优实战', TO_VECTOR('[0.55,0.10,0.44]')),
(4, '向量检索原理', '从 KNN 到 HNSW,深入理解 ANN 算法演进', TO_VECTOR('[0.78,0.32,0.65]')),
(5, '图数据库选型指南','Neo4j / JanusGraph / 原生图能力对比', TO_VECTOR('[0.43,0.71,0.18]'));
-- 方式二: 注册 Embedding 模型后通过 AI_EMBED 函数生成
-- EXEC DBMS_LLM.CREATE_MODEL('embed_model', 'http://host:port', 'model-id', 'embedding', 'openai', 'sk-xxx');
-- INSERT INTO docs VALUES (6, '标题', '内容', AI_EMBED('embed_model', '文本内容', 3));

使用 <-> 操作符进行精确 KNN 检索,向量维度需一致。
SELECT id, title FROM docs
ORDER BY embedding <-> TO_VECTOR('[0.78,0.32,0.65]', 3)
FETCH FIRST 3 ROWS ONLY;
-- 预期结果: top1 为 id=4(与查询向量完全相同)
-- id=4, title=向量检索原理
-- id=3, title=传统SQL优化技巧
-- id=2, title=AI时代的数据库

HNSW索引参数: M控制每层最大连接数,efConstruction控制构建时搜索范围。
CREATE VECTOR INDEX idx_docs_emb ON docs(embedding)
ORGANIZATION NEIGHBOR GRAPH WITH DISTANCE COSINE
PARAMETERS (TYPE HNSW, M 16, efConstruction 64);

使用FETCH APPROX语法利用HNSW索引加速:
EXPLAIN SELECT id, title FROM docs
ORDER BY embedding <-> TO_VECTOR('[0.78,0.32,0.65]', 3)
FETCH APPROX FIRST 3 ROWS ONLY;

SELECT id, embedding <-> TO_VECTOR('[0.78,0.32,0.65]', 3) AS dist
FROM docs ORDER BY id;
-- id=4 与自身距离 = 0.0(验证正确)

SELECT id, cosine_distance(embedding, TO_VECTOR('[0.78,0.32,0.65]', 3)) AS dist
FROM docs ORDER BY dist FETCH APPROX FIRST 3 ROWS ONLY;
-- top1: id=4, cosine距离最小

SELECT id, title, embedding <-> TO_VECTOR('[0.21,0.65,0.77]', 3) AS dist
FROM docs WHERE id <= 3
ORDER BY dist FETCH FIRST 2 ROWS ONLY;
-- top1: id=2(与查询向量相同,且在 id<=3 过滤条件下)

功能概述: 基于SQL 2023 SQL/PGQ标准,将图构建为关系数据之上的语义抽象层。零冗余存储、实时一致性、智能查询重写为JOIN+递归CTE。
参考文档: https://doc.yashandb.com/yashandb/23.5.4/zh/All-Manuals/Development-Guide/SQL-Reference-Manual/SQL-Statements/CREATE-PROPERTY-GRAPH.html
CREATE TABLE person (
id INT PRIMARY KEY,
name VARCHAR(100),
age INT
);
CREATE TABLE friendship (
src_id INT,
dst_id INT,
since DATE,
PRIMARY KEY (src_id, dst_id)
);
INSERT INTO person VALUES (1,'Alice',30),(2,'Bob',28),(3,'Carol',35),(4,'Dave',40);
INSERT INTO friendship VALUES (1,2,DATE'2020-01-01'),(2,3,DATE'2021-05-12'),(3,4,DATE'2022-09-09');

属性图是纯粹的元数据声明,不复制数据:
CREATE PROPERTY GRAPH social
VERTEX TABLES ( person KEY (id) LABEL person PROPERTIES (name, age, id) )
EDGE TABLES (
friendship KEY (src_id, dst_id)
SOURCEKEY (src_id) REFERENCES person(id)
DESTINATION KEY (dst_id) REFERENCES person(id)
LABEL knows PROPERTIES (since)
);

SELECT * FROM GRAPH_TABLE(social
MATCH (a is person)-[r is knows]->(b is person)
WHERE a.name = 'Alice'
COLUMNS (b.name AS friend, r.since AS since)
);
-- 预期: friend=Bob, since=2020-01-01

SELECT * FROM GRAPH_TABLE(social
MATCH (a is person)-[r is knows]->{1,2}(b is person)
WHERE a.name = 'Alice'
COLUMNS (b.name AS friend, count(r.since) AS hops)
);
-- 预期: Bob(1跳) + Carol(2跳)

SELECT * FROM GRAPH_TABLE(social
MATCH (a is person)-[r is knows]->(b is person)
WHERE b.name = 'Bob'
COLUMNS (a.name AS knows_bob)
);
-- 预期: Alice

功能概述: YashanDB提供原生JSON数据类型,采用二进制格式存储,路径表达式访问优化。支持JSON_VALUE(标量提取)、JSON_QUERY(片段提取)、JSON_EXISTS(路径判断)、JSON_SERIALIZE(序列化)等标准函数,以及函数索引加速固定路径查询。
参考文档: https://doc.yashandb.com/yashandb/23.5/zh/All-Manuals/Development-Guide/SQL-Reference-Manual/General-SQL-Syntax/json.html
JSON 表必须使用 ORGANIZATION HEAP:
CREATE TABLE products (
id BIGINT PRIMARY KEY,
name VARCHAR(100),
details JSON
) ORGANIZATION HEAP;
INSERT INTO products VALUES
(1, 'YashanDB',
JSON('{"version":"23.5.4","tags":["多模","AI"],"specs":{"cpu":16,"mem_gb":64}}')),
(2, 'Neo4j',
JSON('{"version":"5.0","tags":["graph"],"specs":{"cpu":8,"mem_gb":32}}'));

SELECT id, name, JSON_VALUE(details, '$.version') ASversion
FROM products ORDER BY id;
-- 预期:
-- id=1, name=YashanDB, version=23.5.4
-- id=2, name=Neo4j, version=5.0

SELECT id, name FROM products
WHERE JSON_EXISTS(details, '$.specs.cpu')
ORDER BY id;
-- 预期: 返回两条(都有 specs.cpu)

SELECT id, name, JSON_QUERY(details, '$.specs') AS specs
FROM products ORDER BY id;
-- 预期:
-- id=1, specs={"cpu":16,"mem_gb":64}
-- id=2, specs={"cpu":8,"mem_gb":32}

问题发现: JSON_QUERY 返回 VARCHAR 类型而非 JSON 类型,直接传给 JSON_ARRAY_GET 会报类型不匹配错误:
YAS-04401 data type JSON expected, but VARCHAR got
解决方案对比:
-- [不推荐] 直接传JSON_QUERY结果 → 失败
SELECT JSON_ARRAY_GET(JSON_QUERY(details, '$.tags'), 0) FROM products;
-- 报错: YAS-04401 data type JSON expected, but VARCHAR got
-- [可行] CAST为JSON后再传
SELECT JSON_SERIALIZE(JSON_ARRAY_GET(JSON(JSON_QUERY(details, '$.tags')), 0))
FROM products WHERE id = 1;
-- 结果: "多模"
-- [最佳实践] 直接用JSON_VALUE+路径下标
SELECT
JSON_VALUE(details, '$.tags[0]') AS tag0,
JSON_VALUE(details, '$.tags[1]') AS tag1,
JSON_VALUE(details, '$.specs.cpu') AS cpu
FROM products WHERE id = 1;
-- 结果: tag0=多模, tag1=AI, cpu=16

-- 紧凑格式
SELECT JSON_SERIALIZE(details) AS compact FROM products WHERE id = 1;
-- 美化格式
SELECT JSON_SERIALIZE(details PRETTY) AS pretty FROM products WHERE id = 1;

功能概述: YashanDB将文件提升为数据库内的原生存储对象,文件与业务表共享同一套ACID与MVCC,支持统一的备份恢复和安全管控。当前仅支持单机部署。
参考文档: https://doc.yashandb.com/yashandb/23.5/zh/SQL-Guide/Built-in-Packages/DBMS_FS.html
DBMS_FS 必须使用 DATABUCKET 方式创建表空间:
CREATE TABLESPACE doc_tbs
DATABUCKET 'doc_bucket'
MAXSIZE 10G;

卷绑定表空间和数据桶,指定最大容量(字节):
BEGIN
DBMS_FS.CREATE_VOLUME('doc_vol', 'doc_tbs', 'doc_bucket', 1073741824);
END;
/

卷作用域为会话级别,需在每个 PL/SQL 块中设置:
BEGIN
DBMS_FS.SET_VOLUME('doc_vol');
DBMS_FS.MKDIR('/data');
END;
/

BEGIN
DBMS_FS.SET_VOLUME('doc_vol');
DBMS_FS.MKDIR('/data/docs');
DBMS_FS.CREATE('/data/docs/readme.txt');
DBMS_FS.WRITE('/data/docs/readme.txt', 'Hello YashanDB File System!');
COMMIT;
END;
/

READ需要5个参数: path, offset, length, content (OUT), len (OUT):
DECLARE
v_content VARCHAR2(4000);
v_len BINARY_INTEGER;
BEGIN
DBMS_FS.SET_VOLUME('doc_vol');
DBMS_FS.READ('/data/docs/readme.txt', 0, 4000, v_content, v_len);
DBMS_OUTPUT.PUT_LINE('Content: ' || v_content);
END;
/

DECLARE
v_entries DBMS_FS.DIRENTRY_TABLE;
v_count INTEGER;
BEGIN
DBMS_FS.SET_VOLUME('doc_vol');
DBMS_FS.LISTDIR('/data', v_entries, v_count);
DBMS_OUTPUT.PUT_LINE('Items: ' || v_count);
END;
/

DECLARE
v_exists BOOLEAN;
BEGIN
DBMS_FS.SET_VOLUME('doc_vol');
DBMS_FS.EXIST('/data/docs/readme.txt', v_exists);
IF v_exists THEN
DBMS_OUTPUT.PUT_LINE('File exists');
END IF;
END;
/

功能概述: YashanDB全文检索的倒排索引直接构建在数据页上,索引更新随事务原子落盘。支持中英文混合分词、大小写不敏感、布尔组合(AND/OR/NOT)、短语精确匹配、词形归一。全文索引可与向量索引共存于同一表。
参考文档: https://doc.yashandb.com/yashandb/23.5.4/zh/All-Manuals/Development-Guide/SQL-Reference-Manual/SQL-Statements/CREATE-INDEX.html#SEARCH
CREATE TABLE articles (
id BIGINT PRIMARY KEY,
title VARCHAR(200),
body CLOB
);
INSERT INTO articles VALUES
(1, '多模数据库白皮书', '本文讨论原生多模数据库的技术路线与产品演进'),
(2, 'AI 数据库评测', 'AI 时代数据库需要支持向量、图、文档等多种模型'),
(3, '传统 SQL 优化', '索引设计是关系型数据库性能的核心');

CREATE SEARCH INDEX articles_idx ON articles(body);

SELECT id, title FROM articles WHERE CONTAINS(body, '数据库') > 0;
-- 预期: 返回3行(所有文章都包含"数据库")

SELECT id, title FROM articles
WHERE CONTAINS(body, '数据库') > 0 AND CONTAINS(body, '多模') > 0;
-- 预期: id=1(同时包含"数据库"和"多模")

SELECTid FROM articles
WHERE CONTAINS(body, '数据库') > 0 AND CONTAINS(body, '模型') > 0;
-- 预期: id=2(包含"数据库"和"模型")

同一张表同时创建向量索引和全文索引:
CREATE TABLE tb_company (
id INT,
name VARCHAR(200),
embedding VECTOR(3)
);
INSERT INTO tb_company VALUES
(1, 'oceanbase', TO_VECTOR('[1,0,0]')),
(2, 'oracle database', TO_VECTOR('[1,0,3]')),
(3, 'yashan database', TO_VECTOR('[1,0,2]')),
(4, 'tidb', TO_VECTOR('[1,0,1]'));
-- 创建向量索引
CREATE VECTOR INDEX vidx1 ON tb_company (embedding)
ORGANIZATION NEIGHBOR GRAPH DISTANCE COSINE;
-- 在同一表上创建全文索引
CREATE SEARCH INDEX sidx2 ON tb_company(name);
-- 全文检索
SELECT id, nameFROM tb_company WHERE CONTAINS(name, 'database') > 0;
-- 预期: id=2 (oracle database), id=3 (yashan database)

功能概述: YashanDB提供内核原生的GIS引擎,支持OGC标准几何类型(Point/LINESTRING/POLYGON 及 MULTI* 集合),R-Tree空间索引,国内外主流坐标系(北京54、西安80、中国2000、WGS84)。
参考文档: https://doc.yashandb.com/yashandb/23.5.4/zh/All-Manuals/Development-Guide/SQL-Reference-Manual/Data-Types/ST_GEOMETRY-Type.html
CREATE TABLE city_buildings (
id BIGINT PRIMARY KEY,
name VARCHAR(100),
geom GEOMETRY(point, 4326) -- WGS 84 坐标系
);
INSERT INTO city_buildings VALUES (1, 'A 楼', ST_GeomFromText('POINT(116.397 39.908)'));
INSERT INTO city_buildings VALUES (2, 'B 楼', ST_GeomFromText('POINT(121.473 31.230)'));
INSERT INTO city_buildings VALUES (3, 'C 楼', ST_GeomFromText('POINT(113.264 23.129)'));

CREATE RTREE INDEX idx_geom ON city_buildings(geom);
-- 查询落入指定矩形范围的建筑
SELECT id, name FROM city_buildings
WHERE ST_Contains(
ST_GeomFromText('POLYGON((110 30, 120 30, 120 40, 110 40, 110 30))', 4326),
geom
);
-- 预期: id=1 (A 楼,天安门在 (110-120, 30-40) 范围内)

-- WGS 84 (4326) 转 中国 2000 (4490)
SELECT id, name, ST_AsText(ST_Transform(geom, 4490)) AS geom_cgcs2000
FROM city_buildings WHERE id = 1;
-- 预期: POINT (116.397... 39.908...)

SELECT a.name AS loc_a, b.name AS loc_b,
ST_Distance(a.geom, b.geom) AS dist
FROM city_buildings a, city_buildings b
WHERE a.id = 1 AND b.id = 2;
-- 预期: A 楼 -> B 楼 (北京到上海) ≈ 1066 km

功能概述: 所有模态共享同一个查询优化器与执行引擎,一条SQL可同时跨越关系表、向量、全文、图、JSON 等多种模态。
SELECT id, name FROM tb_company WHERE CONTAINS(name, 'database') > 0
UNION
(SELECT id, nameFROM tb_company
ORDER BY cosine_distance(embedding, TO_VECTOR('[1, 1, 1]', 3))
FETCH APPROXIMATE FIRST 2 ROWS ONLY);
-- 预期: 返回 3 行(全文匹配2条 + 向量top2去重后共3条)

CREATE OR REPLACE VIEW entity AS
SELECT id, name FROM tb_company
WHERE CONTAINS(name, 'database') > 0 AND id > 1
UNION
(SELECT id, name FROM tb_company
ORDER BY cosine_distance(embedding, TO_VECTOR('[1, 1, 1]', 3))
FETCH APPROXIMATE FIRST 2 ROWS ONLY);

CREATE TABLE relation (
r_id INT,
s_entity_id INT,
d_entity_id INT,
label VARCHAR(20)
);
INSERT INTO relation VALUES (1, 1, 2, 'label1');
INSERT INTO relation VALUES (2, 1, 3, 'label2');
INSERT INTO relation VALUES (3, 1, 4, 'label3');
INSERT INTO relation VALUES (4, 3, 4, 'label4');
INSERT INTO relation VALUES (5, 2, 3, 'label5');
INSERT INTO relation VALUES (6, 3, 2, 'label6');

在全文+向量融合视图之上构建图语义:
CREATE PROPERTY GRAPH entity_graph
VERTEX TABLES (
entity KEY (id)
LABEL entity_prop
PROPERTIES (name)
)
EDGE TABLES (
relation KEY (r_id)
SOURCE KEY (s_entity_id) REFERENCES entity(id)
DESTINATION KEY (d_entity_id) REFERENCES entity(id)
LABEL relation_prop
PROPERTIES (label)
);

SELECT aname, label, bname
FROM GRAPH_TABLE(entity_graph
MATCH (a is entity_prop)-[r is relation_prop]->(b is entity_prop)
COLUMNS (a.name AS aname, r.label AS label, b.name AS bname)
);
-- 预期: 返回视图 entity 内节点之间的所有边关系
-- 如: yashan database -> oracle database, oracle database -> yashan database 等

模态 | 测试项 | 通过 | 失败 |
|---|---|---|---|
模态1: 向量能力 | 8 | 8 | 0 |
模态2: 图能力 | 5 | 5 | 0 |
模态3: 文档/JSON | 6 | 6 | 0 |
模态4: 文件管理 | 7 | 7 | 0 |
模态5: 全文检索 | 6 | 6 | 0 |
模态6: 空间能力 | 4 | 4 | 0 |
跨模态融合 | 5 | 5 | 0 |
JSON_ARRAY_GET 探索 | 3 | 3 | 0 |
合计 | 44 | 44 | 0 |
通过本文的对YashanDB v23.5.4 AI Edition多模能力的完整测试,可以看出崖山数据库已经达到了我心目中AI数据库的要求,我也即将开始适配工作。
老规矩,知道写了些啥。