DawnSql解决SAAS的痛点
SAAS 系统的痛点
1、大客户定制化程度高
2、客户对自身数据安全的担忧,如何防止数据的泄露也滥用
DawnSql 的解决方案
众所周知,软件 = 程序 + 数据。
- 如果客户的数据需要上传到 SAAS 厂商的服务器,那么 SAAS 厂商只需要对相应的数据设置用户组,并对这个用户组设置相应的权限,就可以将该用户组的权限,发给客户,客户就可以根据自己的实际需求来修改、扩展相应的功能!
- 客户对自身数据安全的担忧。客户只需要将自己的数据根据 SAAS 厂商提供的表格式部署到 DawnSql中,同时设置好用户组权限,SAAS厂商就可以使用这个用户组来访问数据,用户直接使用 SAAS厂商提供的服务即可。
DawnSql 例子
所有的例子来自于,NorthWind 实例数据库。
1、设置配置文件
1.1、设置 consistentId,如果是集群的话,每个节点的 consistentId 应该是不一样,这个属性可以不设置。(不过我们建议设置)
<property name="consistentId" value="dawn_node"></property>
1.2、设置超级管理员的 root token
<!-- 超级管理员的 root token, 用户可以直接来设置一个 root token -->
<!-- 本例中 root token 为 dafu -->
<property name="root_token" value="dafu"/>
1.3、用户是否实现了 log 事务接口。默认是没有实现,这个需要用户根据自己的实际需求来实现。
<!-- 设置实现 log 事务接口的类 -->
<!--
<property name="myLogCls" value="org.gridgain.smart.logClient.MyLogTransactionClient"/>
-->
1.4、是否实现了初始化后就执行的方法,默认是没有实现
<!-- 设置启动的时候,初始化 rpc 服务器 -->
<!-- org.dawn.rpc.MyRpcStartImpl 是实现了 IDawnSqlStart 接口的类 -->
<!-- 不设置则不启动这个服务,具体代码可以参看开源的例子 -->
<!--
<property name="startAppCls" value="org.dawn.rpc.MyRpcStartImpl"/>
-->
1.5、创建表的模板 (这个是必须要设置的)
例子中设置了两个模板:
base 模板:复制模式,支持事务
manage 模板:分区模式,同一份数据,在集群中备份 3 次,支持事务
<!-- 创建表的模板 -->
<property name="templateConfiguration">
<map key-type="java.lang.String" value-type="org.apache.ignite.configuration.TableTemplateConfiguration">
<entry key="base">
<bean class="org.apache.ignite.configuration.TableTemplateConfiguration">
<property name="templateValue" value="template=REPLICATED,ATOMICITY=TRANSACTIONAL"></property>
<property name="description" value="复制模式,来保存数据!"></property>
</bean>
</entry>
<entry key="manage">
<bean class="org.apache.ignite.configuration.TableTemplateConfiguration">
<property name="templateValue" value="template=partitioned,backups=3,ATOMICITY=TRANSACTIONAL"></property>
<property name="description" value="分片模式,来保存数据!"></property>
</bean>
</entry>
</map>
</property>
2、创建表
-- 1、产品类型表
CREATE TABLE IF NOT EXISTS public.Categories (
-- 产品类型ID
CategoryID INTEGER NOT NULL auto,
-- 产品类型名
CategoryName VARCHAR(15) NOT NULL,
-- 类型说明
Description VARCHAR,
-- 产品样本
Picture VARCHAR,
PRIMARY KEY (CategoryID)
) WITH "template=manage";
-- 2、 顾客信息表
CREATE TABLE IF NOT EXISTS public.Customers (
-- 客户ID
CustomerID VARCHAR(5) NOT NULL,
-- 所在公司名称
CompanyName VARCHAR(40) NOT NULL,
-- 客户姓名
ContactName VARCHAR(30),
-- 客户头衔
ContactTitle VARCHAR(30),
-- 联系地址
Address VARCHAR(60),
-- 所在城市
City VARCHAR(15),
-- 所在地区
Region VARCHAR(15),
-- 邮编
PostalCode VARCHAR(10),
-- 国家
Country VARCHAR(15),
-- 电话
Phone VARCHAR(24),
-- 传真
Fax VARCHAR(24),
PRIMARY KEY (CustomerID)
) WITH "template=manage";
-- 3、 产品类别表
CREATE TABLE IF NOT EXISTS public.Products (
-- 产品ID
ProductID INTEGER NOT NULL,
-- 产品名称
ProductName VARCHAR(40) NOT NULL,
-- 供应商ID
SupplierID INTEGER,
-- 类型ID
CategoryID INTEGER,
-- 数量
QuantityPerUnit VARCHAR(20),
-- 单价
UnitPrice DECIMAL(10,4) DEFAULT 0,
-- 库存数量
UnitsInStock SMALLINT(2) DEFAULT 0,
-- 订购量
UnitsOnOrder SMALLINT(2) DEFAULT 0,
-- 再次订购量
ReorderLevel SMALLINT(2) DEFAULT 0,
-- 中止
Discontinued BIT NOT NULL DEFAULT 0,
PRIMARY KEY (ProductID)
) WITH "template=manage";
-- 4、 运货商
CREATE TABLE IF NOT EXISTS Shippers (
-- 运货商ID
ShipperID INTEGER NOT NULL auto,
-- 公司名称
CompanyName VARCHAR(40) NOT NULL,
-- 联系电话
Phone VARCHAR(24),
PRIMARY KEY (ShipperID)
) WITH "template=manage";
-- 5、 供应商表
CREATE TABLE IF NOT EXISTS Suppliers (
-- 地区描述
SupplierID INTEGER NOT NULL,
-- 供应商姓名
CompanyName VARCHAR(40) NOT NULL,
-- 联系人
ContactName VARCHAR(30),
-- 联系人职务
ContactTitle VARCHAR(30),
-- 地址
Address VARCHAR(60),
-- 城市
City VARCHAR(15),
-- 销售大区域
Region VARCHAR(15),
-- 邮政编码
PostalCode VARCHAR(10),
-- 国家
Country VARCHAR(15),
-- 联系电话
Phone VARCHAR(24),
-- 传真
Fax VARCHAR(24),
-- 首页
HomePage VARCHAR,
PRIMARY KEY (SupplierID)
) WITH "template=manage";
-- 6、 雇员表,存放员工的一些基本信息
CREATE TABLE IF NOT EXISTS Employees (
-- 员工编号
EmployeeID INTEGER NOT NULL,
-- 员工姓
LastName VARCHAR(20) NOT NULL,
-- 员工名
FirstName VARCHAR(10) NOT NULL,
-- 头衔
Title VARCHAR(30),
-- 尊称
TitleOfCourtesy VARCHAR(25),
-- 出生日期
BirthDate DATETIME,
-- 雇用日期
HireDate DATETIME,
-- 家庭地址
Address VARCHAR(60),
-- 所在城市
City VARCHAR(15),
-- 所在地区
Region VARCHAR(15),
-- 邮编
PostalCode VARCHAR(10),
-- 国家
Country VARCHAR(15),
-- 住宅电话
HomePhone VARCHAR(24),
-- 分机
Extension VARCHAR(4),
-- 照片
Photo VARCHAR,
-- 备注
Notes VARCHAR NOT NULL,
-- 上级
ReportsTo VARCHAR,
-- 照片路径
PhotoPath VARCHAR(255),
-- 工资
Salary FLOAT,
PRIMARY KEY (EmployeeID)
) WITH "template=manage";
-- 7、 雇员销售区域表
CREATE TABLE EmployeeTerritories (
-- ID
ID INTEGER NOT NULL auto,
-- 员工编号
EmployeeID INTEGER NOT NULL,
-- 区域代号
TerritoryID VARCHAR(20) NOT NULL,
PRIMARY KEY (ID)
) WITH "template=manage";
-- 8、 销售小区域表
CREATE TABLE Territories (
-- 地域编号
TerritoryID VARCHAR(20) NOT NULL,
-- 地域描述
TerritoryDescription VARCHAR(50) NOT NULL,
-- 地区编号
RegionID INTEGER NOT NULL,
PRIMARY KEY (TerritoryID)
) WITH "template=manage";
-- 9、 订单详情表
CREATE TABLE OrderDetails (
-- 订单编号
OrderID INTEGER NOT NULL,
-- 产品编号
ProductID INTEGER NOT NULL,
-- 单价
UnitPrice DECIMAL(10,4) DEFAULT 0,
-- 订购数量
Quantity SMALLINT(2) DEFAULT 1,
-- 折扣
Discount REAL(8,0) NOT NULL,
PRIMARY KEY (OrderID, ProductID)
) WITH "template=manage,affinity_key=ProductID";
-- 10、 订单表
CREATE TABLE IF NOT EXISTS Orders (
-- 订单编号
OrderID INTEGER NOT NULL,
-- 客户编号
CustomerID VARCHAR(5),
-- 员工编号
EmployeeID INTEGER,
-- 订购日期
OrderDate DATETIME,
-- 预计到达日期
RequiredDate DATETIME,
-- 发货日期
ShippedDate DATETIME,
-- 运货商
ShipVia INTEGER,
-- 运费
Freight DECIMAL(10,4) DEFAULT 0,
-- 货主姓名
ShipName VARCHAR(40),
-- 货主地址
ShipAddress VARCHAR(60),
-- 货主所在城市
ShipCity VARCHAR(15),
-- 货主所在地区
ShipRegion VARCHAR(15),
-- 货主邮编
ShipPostalCode VARCHAR(10),
-- 货主所在国家
ShipCountry VARCHAR(15),
PRIMARY KEY (OrderID)
) WITH "template=manage";
3、导入数据
在 DawnSql 中导入数据有两种方式。
- 通过 JDBC 来 insert 来导入数据。
例如:
由于要插入的数据比较多,所以这里只做实例,具体的数据,我们放在文档后面的下载链接中。
INSERT INTO Categories (CategoryName, Description, Picture) VALUES('Beverages','Soft drinks, coffees, teas, beers, and ales', '');
INSERT INTO Categories (CategoryName, Description, Picture) VALUES('Condiments','Sweet and savory sauces, relishes, spreads, and seasonings', '');
用 JDBC 导入
Class.forName("org.apache.ignite.IgniteJdbcDriver");
String url = "jdbc:ignite:thin://127.0.0.1:10800/public?lazy=true&distributedJoins=true&userToken=dafu";
Connection conn = DriverManager.getConnection(url);
Statement stmt = conn.createStatement();
stmt.executeUpdate("SET STREAMING ON; INSERT INTO public.Categories (CategoryName, Description, Picture) VALUES('Seafood','草鱼', ''), ('"+ CategoryName +"', '"+ Description +"', '"+ Picture +"')");
stmt.close();
conn.close();
- 通过 JDBC 批量导入数据。
-- 批量导入
SET STREAMING ON;
INSERT INTO public.Categories (CategoryName, Description, Picture) VALUES('Seafood','草鱼', ''), ('吴大富','金毛', '');
-- 或者
SET STREAMING ON;
INSERT INTO public.Categories (CategoryName, Description, Picture) VALUES ('Seafood','草鱼', '');
INSERT INTO public.Categories (CategoryName, Description, Picture) VALUES ('吴大富','金毛', '');
- 快速批量导入。这种方法可以绕开 SQL 解析,直接将数据存入集群。但是这种方法需要对 Dawn Sql 比较了解且具备一定的编程能力。如果想了解这种方法请联系作者。
4、添加 schema
-- 添加 schema 名字为 myy
create schema myy;
-- 或者
create SCHEMA IF NOT EXISTS myy;
5、添加用户组
-- 添加用户组
add_user_group('myy_group', 'myy_token', 'all', 'myy');
-- 通过 user_token 获取用户组
get_user_group('myy_token');
6、为用户组设置权限
为 myy_group 设置用户权限。
1、
-- 对用户组 myy_group 设置访问 public.Employees 表的权限,让它只能查询
-- EMPLOYEEID < 6 的数据
my_view('myy_group', "SELECT * from public.Employees where EMPLOYEEID < 6");
7、添加方法
-- 统计只出过一单的员工数量
function get_emp_count()
{
let rs = query_sql("SELECT COUNT(DISTINCT o.EmployeeID)
FROM public.Orders o
LEFT JOIN public.Employees e ON o.EmployeeID=e.EmployeeID");
rs.next().FIRST();
}
-- 查询只卖过一件商品
SELECT p.ProductName,COUNT(DISTINCT wo.EmployeeID)
FROM public.Orders wo
JOIN public.Employees e ON wo.EmployeeID=e.EmployeeID
JOIN public.OrderDetails od ON wo.OrderID=od.OrderID
JOIN public.Products p ON od.ProductID=p.ProductID
GROUP BY p.ProductName
HAVING COUNT(DISTINCT wo.EmployeeID) = get_emp_count();
8、用 NoSql 来描述业务流程或提升程序性能
8.1、在 to B 的系统中业务的流程和规则往往特别的复杂,业务变动大,时效性要求高
例如:在保险中,代理人的组织结构是金字塔型的,佣金项几十个,不同的产品有不同的佣金比例,代理人级别不同也有所不同。可以将代理人的em_no 作为主键,将代理的上下级、保单、佣金项作为数据,形成一个树形结构。当保单改变,或者上下级变化时候,动态修改该树。当需要计算佣金的时候,只需要扫描这棵树的佣金项即可。
8.2、在需要对海量数据高并发读写的场景下
具体用法:NoSql 的支持
9、DawnSql的 root 用户可以自己扩展方法
具体方法:自定义扩展方法
推荐阅读
H2存储内核分析一
现在做数据库一般都才有 C/C++ 获取其它编译型的语言,为什么会选择 h2 这种基于 java 的语言?会不会影响效率?其实回答这个问题很简单,无论是用什么语言来实现数据库,其实都是在调用操作系统 IO 的函数。因此...
monk0123456阅读 300
TOPI 简介
这是 TVM 算子清单(TOPI)的入门教程。 TOPI 提供了 numpy 风格的通用操作和 schedule,其抽象程度高于 TVM。本教程将介绍 TOPI 是如何使得 TVM 中的代码不那么样板化的。
超神经HyperAI赞 1阅读 90.7k
编译 MXNet 模型
本篇文章译自英文文档 Compile MXNet Models。作者是 Joshua Z. Zhang,Kazutaka Morita。更多 TVM 中文文档可访问 →TVM 中文站。本文将介绍如何用 Relay 部署 MXNet 模型。首先安装 mxnet 模块,可通过 pip 快速...
超神经HyperAI赞 1阅读 61.1k
编译 PyTorch 模型
本篇文章译自英文文档 Compile PyTorch Models。作者是 Alex Wong。更多 TVM 中文文档可访问 →TVM 中文站。本文介绍了如何用 Relay 部署 PyTorch 模型。首先应安装 PyTorch。此外,还应安装 TorchVision,并将其...
超神经HyperAI赞 1阅读 93.1k
科罗拉多州立大学发布CSU-MLP模型,用随机森林预测中期恶劣天气
内容一览:近期,来自美国科罗拉多州立大学与 SPC 的相关学者联合发布了一个基于随机森林的机器学习模型 CSU-MLP,该模型能够对中期 (4-8天) 范围内恶劣天气进行准确预报。目前该成果刊已发表在《Weather and For...
超神经HyperAI阅读 63.8k
利用 UMA 使硬件加速器可直接用于 TVM
本篇文章译自英文文档 Making your Hardware Accelerator TVM-ready with UMA作者是 Michael J. Klaiber,Christoph Gerum,Paul Palomero Bernardo。更多 TVM 中文文档可访问 →TVM 中文站本节介绍通用模块化加速器...
超神经HyperAI阅读 94.1k
借助计算机建模及 eBird 数据集,马萨诸塞大学成功预测鸟类迁徙
本文首发自 HyperAI超神经微信公众号~内容一览:近日,英国生态学会期刊《Methods in Ecology and Evolution》上发布了一个新的预测模型 BirdFlow,其能够解决生物学目前最困难的挑战之一:准确预测候鸟的运动轨...
超神经HyperAI阅读 89.7k
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。