SQLite から SPL までの Java 組み込みデータ エンジンの分析例

WBOY
リリース: 2023-05-05 21:52:05
転載
682 人が閲覧しました

Java アプリケーションに組み込めるデータ エンジンは豊富にあるように見えますが、実際には選択するのは簡単ではありません。 Redis はコンピューティング能力が低く、単純なクエリ シナリオにのみ適しています。 Spark アーキテクチャは複雑で重いため、展開とメンテナンスが非常に面倒です。 H2\HSQLDB\Derby などの組み込みデータベースは単純な構造ですが、コンピューティング能力が不十分であり、基本的なウィンドウ関数さえサポートしていません。

対照的に、SQLite はアーキテクチャとコンピューティング能力のより良いバランスを実現しており、広く使用されている Java 組み込みデータ エンジンです。

SQLite は従来の基本的なアプリケーション シナリオに適応します

SQLite はシンプルな構造を持ち、そのコアは C 言語で開発されていますが、適切にカプセル化され、小さな Jar パッケージとして外部に提供されます。 Java アプリケーションに簡単に統合できます。 SQLite は、Java から呼び出すことができる JDBC インターフェイスを提供します。

Connection connection = DriverManager.getConnection("jdbc:sqlite::memory:");
Statement st = connection.createStatement();
st.execute("restore from d:/ex1");
ResultSet rs = st.executeQuery("SELECT * FROM orders");
ログイン後にコピー

SQLite は標準の SQL 構文を提供し、従来のデータ処理と計算には問題ありません。特に、SQLite はすでにウィンドウ関数をサポートしており、多くのグループ内操作を簡単に実装でき、他の組み込みデータベースよりも強力な計算能力を備えています。

SELECT x, y, row_number() OVER (ORDER BY y) AS row_number FROM t0 ORDER BY x;
SELECT a, b, group_concat(b, '.') OVER ( ORDER BY a ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) AS group_concat FROM t1;
ログイン後にコピー

SQLite には、複雑なシナリオに直面した場合にはまだ欠点があります

SQLite には優れた利点がありますが、複雑なアプリケーション シナリオに関してはまだいくつかの欠点があります。

Java アプリケーションは、csv ファイル、RDB、Excel、Restful などのさまざまなデータ ソースを処理できますが、SQLite は単純なケースのみを処理します。つまり、SQLite は、次のようなテキスト ファイルに対して直接利用可能なコマンド ライン ローダーを提供します。 csv として。 :

.import --csv --skip 1 --schema temp /Users/scudata/somedata.csv tab1
ログイン後にコピー

他のほとんどのデータ ソースの場合、SQLite は便利なインターフェイスを提供しません。データを読み込むコードを直接記述することしかできず、コマンド ラインを複数回呼び出す必要があります。プロセス全体が非常に面倒です。そしてタイムリー。

RDB データ ソースのロードを例に挙げると、一般的なアプローチは、まず Java を使用してコマンド ラインを実行し、RDB ライブラリ テーブルを CSV に変換し、次に JDBC を使用して SQLite にアクセスし、テーブル構造を作成します。 Java を使用してコマンド ラインを実行し、csv ファイルを SQLite にインポートし、最後に新しいテーブルにインデックスを付けてパフォーマンスを向上させます。この方法は比較的厳密な方法であるため、テーブル構造やテーブル名を柔軟に定義したり、ロードされるデータを計算によって決定したい場合は、コードを記述するのがより困難になります。

同様に、他のデータ ソースの場合、SQLite は直接読み込むことができず、面倒な変換プロセスを経る必要があります。

SQL は自然言語に近く、学習閾値が低く、単純な計算の実装が容易ですが、複雑な集合計算、順序計算、関連計算、多重計算などの複雑な計算は苦手です。 -ステップ計算。 SQLiteでは計算にSQL文を使用するため、SQLの長所と短所が引き継がれており、複雑な計算をそのまま実装すると煩雑でわかりにくいコードになってしまいます。

たとえば、特定の株の最長上昇日数を求める場合、SQL は次のように記述する必要があります:

select max(continuousDays)-1
from (select count(*) continuousDays
from (select sum(changeSign) over(order by tradeDate) unRiseDays
from (select tradeDate,
case when price>lag(price) over(order by tradeDate) then 0 else 1 end changeSign from AAPL) )
group by unRiseDays)
ログイン後にコピー

これは SQLite だけの問題ではありません。集計、シリアル番号の欠如、およびオブジェクト参照などの理由により、他の SQL データベースはこれらの操作が苦手です。

ビジネス ロジックは、構造化データの計算とプロセス制御で構成されます。SQLite は SQL をサポートしており、構造化データの計算機能を備えています。ただし、SQLite はストアド プロシージャを提供しておらず、独立したプロセス制御機能を備えていないため、一般的なビジネスを実装できませんロジックは通常、Java メインプログラムの判定文やループ文を使用します。 Java には SQLite データ テーブルやレコードを運ぶための専門的な構造化データ オブジェクトがないため、変換プロセスが煩雑で、処理プロセスがスムーズではなく、開発効率も高くありません。

前述したように、SQLite コアは C プログラムです。Java アプリケーションに統合できますが、Java とシームレスに統合することはできません。Java メイン プログラムとのデータ交換には時間のかかる変換が必要です。パフォーマンスは低下します。大量のデータが関与する場合、または相互作用が頻繁に行われる場合には、大幅に不十分になります。また、カーネルは C プログラムであるため、SQLite は Java アーキテクチャの一貫性と堅牢性をある程度破壊します。

Java アプリケーションの場合は、JVM 上でネイティブに esProc SPL を使用することをお勧めします。

SPL はさまざまなデータ ソースを完全にサポートします

esProc SPL は、JVM 下のオープン ソースの組み込みデータ エンジンです。シンプルなアーキテクチャを持ち、データ ソースを直接ロードできます。統合して呼び出すことができます。 Java は JDBC インターフェイスを介して実行され、後続の計算に便利です。

SPL はシンプルなアーキテクチャであり、独立したサービスを必要とせず、SPL Jar パッケージを導入していれば Java 環境にデプロイできます。

データ ソースを直接ロードします。コードは短く、プロセスはシンプルで、適時性が高くなります。たとえば、Oracle をロードします:

A
#1=connect ( "orcl")
2=A1.query@x("OrderID による注文から OrderID、Client、SellerID、OrderDate、Amount を選択")
3>env(orders,A2)

对于SQLite擅长加载的csv文件,SPL也可以直接加载,使用内置函数而不是外部命令行,稳定且效率高,代码更简短:

=T("/Users/scudata/somedata.csv")
ログイン後にコピー

多种外部数据源。除了RDB和csv,SPL还直接支持txt\xls等文件,MongoDB、Hadoop、redis、ElasticSearch、Kafka、Cassandra等NoSQL,以及WebService XML、Restful Json等多层数据。比如,将HDSF里的文件加载到内存:

A
1=hdfs_open(;"hdfs://192.168.0.8:9000")
2=hdfs_file(A1,"/user/Orders.csv":"GBK")
3=A2.cursor@t()
4=hdfs_close(A1)
5>env(orders,A4)

JDBC接口可以方便地集成。加载的数据量一般比较大,通常在应用的初始阶段运行一次,只须将上面的加载过程存为SPL脚本文件,在Java中以存储过程的形式引用脚本文件名:

Class.forName("com.esproc.jdbc.InternalDriver");
Connection conn =DriverManager.getConnection("jdbc:esproc:local://");
CallableStatement statement = conn.prepareCall("{call init()}");
statement.execute();
ログイン後にコピー

SPL的计算能力更强大

SPL提供了丰富的计算函数,可以轻松实现日常计算。SPL支持多种高级语法,大量的日期函数和字符串函数,很多用SQL难以表达的计算,用SPL都可以轻松实现,包括复杂的有序计算、集合计算、分步计算、关联计算,以及带流程控制的业务逻辑。

丰富的计算函数。SPL可以轻松实现各类日常计算:

AB
1=Orders.find(arg_OrderIDList)//多键值查找
2=Orders.select(Amount>1000 && like(Client,\"*S*\"))//模糊查询
3= Orders.sort(Client,-Amount)//排序
4= Orders.id(Client)//去重
5=join(Orders:O,SellerId; Employees:E,EId).new(O.OrderID, O.Client,O.Amount,E.Name,E.Gender,E.Dept)//关联

标准SQL语法。SPL也提供了SQL-92标准的语法,比如分组汇总:

$select year(OrderDate) y,month(OrderDate) m, sum(Amount) s,count(1) c
from {Orders}
Where Amount>=? and Amount<? ;arg1,arg2
ログイン後にコピー

函数选项、层次参数等方便的语法。功能相似的函数可以共用一个函数名,只用函数选项区分差别,比SQL更加灵活方便。比如select函数的基本功能是过滤,如果只过滤出符合条件的第1条记录,可使用选项@1:

T.select@1(Amount>1000)

二分法排序,即对有序数据用二分法进行快速过滤,使用@b:

T.select@b(Amount>1000)

有序分组,即对分组字段有序的数据,将相邻且字段值相同的记录分为一组,使用@b:

T.groups@b(Client;sum(Amount))

函数选项还可以组合搭配,比如:

Orders.select@1b(Amount>1000)

结构化运算函数的参数有些很复杂,比如SQL就需要用各种关键字把一条语句的参数分隔成多个组,但这会动用很多关键字,也使语句结构不统一。SPL使用层次参数简化了复杂参数的表达,即通过分号、逗号、冒号自高而低将参数分为三层:

join(Orders:o,SellerId ; Employees:e,EId)

更丰富的日期和字符串函数。除了常见函数,比如日期增减、截取字符串,SPL还提供了更丰富的日期和字符串函数,在数量和功能上远远超过了SQL,同样运算时代码更短。比如:

季度增减:elapse@q(“2020-02-27”,-3) //返回2019-05-27

N个工作日之后的日期:workday(date(“2022-01-01”),25) //返回2022-02-04

字符串类函数,判断是否全为数字:isdigit(“12345”) //返回true

取子串前面的字符串:substr@l(“abCDcdef”,“cd”) //返回abCD

按竖线拆成字符串数组:“aa|bb|cc”.split(“|”) //返回[“aa”,“bb”,“cc”]

SPL还支持年份增减、求季度、按正则表达式拆分字符串、拆出SQL的where或select部分、拆出单词、按标记拆HTML等大量函数。

简化有序运算。涉及跨行的有序运算,通常都有一定的难度,比如比上期和同期比。SPL使用"字段[相对位置]"引用跨行的数据,可显著简化代码,还可以自动处理数组越界等特殊情况,比SQL窗口函数更加方便。比如,追加一个计算列rate,计算每条订单的金额增长率:

=T.derive(AMOUNT/AMOUNT[-1]-1: rate)
ログイン後にコピー

综合运用位置表达式和有序函数,很多SQL难以实现的有序运算,都可以用SPL轻松解决。比如,根据考勤表,找出连续 4 周每天均出勤达 7 小时的学生:

A
1=Student.select(DURATION>=7).derive(pdate@w(ATTDATE):w)
2=A1.group@o(SID;~.groups@o(W;count(~):CNT).select(CNT==7).group@i(W-W[-1]!=7).max(~.len()):weeks)
3=A2.select(weeks>=4).(SID)

简化集合运算,SPL的集合化更加彻底,配合灵活的语法和强大的集合函数,可大幅简化复杂的集合计算。比如,在各部门找出比本部门平均年龄小的员工:

A
1=Employees.group(DEPT; (a=~.avg(age(BIRTHDAY)),~.select(age(BIRTHDAY)
2=A1.conj(YOUNG)

计算某支股票最长的连续上涨天数:

A
1=a=0,AAPL.max(a=if(price>price[-1],a+1,0))

简化关联计算。SPL支持对象引用的形式表达关联,可以通过点号直观地访问关联表,避免使用JOIN导致的混乱繁琐,尤其适合复杂的多层关联和自关联。比如,根据员工表计算女经理的男员工:

=employees.select(gender:"male",dept.manager.gender:"female")
ログイン後にコピー

方便的分步计算,SPL集合化更加彻底,可以用变量方便地表达集合,适合多步骤计算,SQL要用嵌套表达的运算,用SPL可以更轻松实现。比如,找出销售额累计占到一半的前n个大客户,并按销售额从大到小排序:

AB
2=sales.sort(amount:-1)/销售额逆序排序,可在SQL中完成
3=A2.cumulate(amount)/计算累计序列
4=A3.m(-1)/2/最后的累计即总额
5=A3.pselect(~>=A4)/超过一半的位置
6=A2(to(A5))/按位置取值

流程控制语法。SPL提供了流程控制语句,配合内置的结构化数据对象,可以方便地实现各类业务逻辑。

分支判断语句:

AB
2
3if T.AMOUNT>10000=T.BONUS=T.AMOUNT*0.05
4else if T.AMOUNT>=5000 && T.AMOUNT<10000=T.BONUS=T.AMOUNT*0.03
5else if T.AMOUNT>=2000 && T.AMOUNT<5000=T.BONUS=T.AMOUNT*0.02

循环语句:

AB
1=db=connect("db")
2=T=db.query@x("select * from sales where SellerID=? order by OrderDate",9)
3for T=A3.BONUS=A3.BONUS+A3.AMOUNT*0.01
4 =A3.CLIENT=CONCAT(LEFT(A3.CLIENT,4), " co.,ltd.")
5  …

与Java的循环类似,SPL还可用break关键字跳出(中断)当前循环体,或用next关键字跳过(忽略)本轮循环,不展开说了。

计算性能更好。在内存计算方面,除了常规的主键和索引外,SPL还提供了很多高性能的数据结构和算法支持,比大多数使用SQL的内存数据库性能好得多,且占用内存更少,比如预关联技术、并行计算、指针式复用。

优化体系结构

SPL支持JDBC接口,代码可外置于Java,耦合性更低,也可内置于Java,调用更简单。SPL支持解释执行和热切换,代码方便移植和管理运营,支持内外存混合计算。

外置代码耦合性低。SPL代码可外置于Java,通过文件名被调用,既不依赖数据库,也不依赖Java,业务逻辑和前端代码天然解耦。

对于较短的计算,也可以像SQLite那样合并成一句,写在Java代码中:

Class.forName("com.esproc.jdbc.InternalDriver");
Connection conn =DriverManager.getConnection("jdbc:esproc:local://");
Statement statement = conn.createStatement();
String arg1="1000";
String arg2="2000"
ResultSet result = statement.executeQuery(=Orders.select(Amount>="+arg1+" && Amount<"+arg2+"). groups(year(OrderDate):y,month(OrderDate):m; sum(Amount):s,count(1):c)");
ログイン後にコピー

解释执行和热切换。业务逻辑数量多,复杂度高,变化是常态。良好的系统构架,应该有能力应对变化的业务逻辑。SPL是基于Java的解释型语言,无须编译就能执行,脚本修改后立即生效,支持不停机的热切换,适合应对变化的业务逻辑。

方便代码移植。SPL通过数据源名从数据库取数,如果需要移植,只要改动配置文件中的数据源配置信息,而不必修改SPL代码。SPL支持动态数据源,可通过参数或宏切换不同的数据库,从而进行更方便的移植。为了进一步增强可移植性,SPL还提供了与具体数据库无关的标准SQL语法,使用sqltranslate函数可将标准SQL转为主流方言SQL,仍然通过query函数执行。

方便管理运营。由于支持库外计算,代码可被第三方工具管理,方便团队协作;SPL脚本可以按文件目录进行存放,方便灵活,管理成本低;SPL对数据库的权限要求类似Java,不影响数据安全。

内外存混合计算。有些数据太大,无法放入内存,但又要与内存表共同计算,这种情况可利用SPL实现内外存混合计算。比如,主表orders已加载到内存,大明细表orderdetail是文本文件,下面进行主表和明细表的关联计算:

  A
1 =file("orderdetail.txt").cursor@t()
2 =orders.cursor()
3 =join(A1:detail,orderid ; A2:main,orderid)
4 =A3.groups(year(main.orderdate):y; sum(detail.amount):s)

SQLite使用简单方便,但数据源加载繁琐,计算能力不足。SPL架构也非常简单,并直接支持更多数据源。SPL计算能力强大,提供了丰富的计算函数,可以轻松实现SQL不擅长的复杂计算。SPL还提供多种优化体系结构的手段,代码既可外置也可内置于Java,支持解释执行和热切换,方便移植和管理运营,并支持内外存混合计算。

以上がSQLite から SPL までの Java 組み込みデータ エンジンの分析例の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:yisu.com
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート
私たちについて 免責事項 Sitemap
PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!