シンプルで使いやすい国内データベースは?

JVMに基づくオープンソースのデータ処理言語には、主にKotlin、Scala、SPLが含まれます.以下は、最も効率的なデータ処理言語を見つけるために、3つを水平方向に比較したものです. この記事の適用可能なシナリオは、プロジェクト開発における一般的なデータ処理とビジネス ロジックに設定されています。主に構造化データ、ビッグ データ、および高パフォーマンスは焦点ではなく、メッセージ フローや科学計算などの特別なシナリオは含まれていません。

基本的な機能

適応面

Kotlin の設計の本来の意図は、より効率的に Java を開発することであり、これは Java を含むあらゆるアプリケーション シナリオに適用できます. 一般的な情報管理システムに加えて、WebServer、Android プロジェクト、およびゲーム開発にも使用できます。汎用性。Scala はもともと、最新のプログラミング パラダイムを統合する汎用開発言語として設計されています. 実際には、主にバックエンドのビッグデータ処理に使用されます. 他のタイプのプロジェクトではめったに登場せず、Kotlin ほど汎用性がありません. SPLの元の設計は専門的なデータ処理言語であり、実践は元の意図と一致しています.フロントエンドとバックエンドのデータ処理と大小のデータ処理に適しています.アプリケーションシナリオは比較的焦点が合っています.汎用性は Kotlin ほど良くありません。

プログラミングパラダイム

Kotlin はオブジェクト指向プログラミングに重点を置いていますが、関数型プログラミングもサポートしています。Scala は両方のパラダイムをサポートしており、オブジェクト指向プログラミングは Koltin よりも完全であり、関数型プログラミングは Koltin よりも便利です。SPL はオブジェクト指向プログラミングをサポートしていないと言えます. オブジェクトの概念はありますが、それらの内容を継承したりオーバーロードしたりしません. 関数型プログラミングは Kotlin よりも便利です.

動作モード

Kotlin と Scala はコンパイル型言語で、SPL はインタープリター型言語です。解釈された言語はより柔軟ですが、同じコードのパフォーマンスはわずかに悪くなります。ただし、SPL には豊富で効率的なライブラリ関数があり、全体的なパフォーマンスは弱くなく、ビッグ データに直面すると有利になることがよくあります。

外部クラス ライブラリ

Kotlin はすべての Java ライブラリを使用できますが、専門的なデータ処理ライブラリはありません。Scala は、すべての Java クラス ライブラリを使用することもでき、プロフェッショナルなビッグ データ処理クラス ライブラリ (Spark) が組み込まれています。SPL には組み込みの専門的なデータ処理関数があり、時間の複雑さを抑えた多数の基本的な操作を提供します. 通常、外部の Java クラス ライブラリは必要ありません. 特殊なケースでは、カスタム関数で呼び出すことができます.

IDE とデバッグ

3 つすべてに、グラフィカル IDE と完全なデバッグ機能があります。SPL の IDE はデータ処理用に特別に設計されています. 構造化されたデータ オブジェクトは表形式で表示されます.これは観察するのにより便利です. Kotlin と Scala の IDE は汎用であり、データ処理用に最適化されていないため, 構造化されたデータ オブジェクトを簡単に変換することはできません.観察した。

学習困難

Kotlin は Java よりも少し習得が難しく、Java に習熟している人は簡単に習得できます。Scala の目標は、Java よりもはるかに習得が難しい Java を超えることです。SPL の目標は、Java や SQL のコーディングを単純化することです. 多くの概念は意図的に単純化されており、学習の難易度は非常に低くなります.

コード量

Kotlin の本来の目的は、Java の開発効率を向上させることでした. 公式の主張によると、全体のコード サイズは Java の 20% にすぎません。この点はあまり減りません。Scala には多くのシンタックス シュガーがあり、ビッグ データ処理クラス ライブラリはより専門的ですが、コードの量は Kotlin よりもはるかに少なくなっています。SPL はデータ処理のみに使用され、プロフェッショナリズムが最も強く、インタープリター言語の強力な表現力の特性と相まって、同じタスクを完了するためのコード量は前の 2 つよりも大幅に少なくなります (比較例は後で示します)。学習難易度が低いと説明できる。

文法

データの種類

アトミック データ型: Short、Int、Long、Float、Double、Boolean など、3 つすべてがサポートされています。

日付と時刻の型: Kotlin には、使いやすい日付と時刻の型 (通常は Java のもの) がありません。Scala と SPL の両方に、特殊で便利な日時型があります。

特徴的なデータ型: Kotlin は、数値以外の文字 Char と、null 許容型の Any? をサポートしています。Scala はタプル (固定長のジェネリック コレクション)、組み込みの BigDecimal をサポートしています。SPL は、組み込みの BigDecimal を備えた高性能の多層序数キーをサポートしています。

コレクション型: Kotlin と Scala は Set、List、Map をサポートします。SPL は、シーケンス (List に似た、順序付けられたジェネリック コレクション) をサポートしています。

構造化データ型: Kotlin にはレコード コレクション List<EntityBean> がありますが、メタデータがなく、十分に専門的ではありません。Scala には、Row、RDD、DataSet、DataFrame (この記事ではこれを例として使用します) など、専門的な構造化データ型があります。SPL には、レコード、シーケンス テーブル (この記事ではこれを例として使用します)、内部テーブル圧縮テーブル、外部メモリ レイジー カーソルなど、専門的な構造化データ型があります。

Scala には独自の暗黙的な変換機能があり、理論的には任意のデータ型 (パラメーター、変数、関数、およびクラスを含む) 間で変換でき、元の関数を簡単に変更または拡張できます。

プロセス処理

3つとも基本的な順次実行・判定分岐・ループをサポートしている. 理論上は任意の複雑なプロセス処理を行うことができる. この点についてはあまり議論されていない. 以下では集計データに対するループ構造の利便性を比較することに焦点を当てる. 計算比率を例にとると、Kotlin コードは次のようになります。

mData.forEachIndexed{index,it->
if(index>0) it.Mom= it.Amount/mData[index-1].Amount-1
}

Kotlin の forEachIndexed 関数には、独自のシリアル番号変数とメンバー変数があり、コレクションのループに便利で、添字付きレコードをサポートし、クロスライン計算を簡単に実行できます。Kotlin の欠点は、範囲外の配列を余分に処理することです。

スカラコード:

val w = Window.orderBy(mData("SellerId"))
mData.withColumn("Mom", mData ("Amount")/lag(mData ("Amount"),1).over(w)-1)

Scala の行をまたがる計算は、配列の範囲外を処理する必要がないため、Kotlin よりも便利です。ただし、Scala の構造化データ オブジェクトはサブスクリプト レコードをサポートしておらず、lag 関数を使用して全体として移動することしかできないため、構造化データには不便です。ラグ関数は、汎用性の高い forEach では使用できませんが、withColumn などの単一関数のループ関数で使用できます。関数型プログラミング スタイルと SQL スタイルの基本的な統一を維持するために、ラグ関数もウィンドウ関数と連携する必要があり (Python の遷移関数にはこの要件がありません)、全体的なコードは Kotlin よりも複雑に見えます。

SPL コード:

mData.(Mom=Amount/Amount[-1]-1)

SPL は、構造化されたデータ オブジェクトのフロー制御に対して多くの最適化を実行しました. 最も一般的で一般的に使用されるループ関数である forEach と同様に、SPL は括弧で直接表現でき、極端に単純化されています. SPL にも move 関数がありますが、ここではより直感的な "[relative position]" 構文が使用されています。これはクロスライン計算を実行する際に Kotlin の絶対配置よりも強力であり、Scala の move 関数よりも便利です。上記のコードに加えて、SPL には、構造化データのプロセス処理関数がさらにあります。たとえば、ループの各ラウンドで 1 つのレコードではなく、レコードのバッチを取得する、フィールド値が変更されたときにループするなどです。

ラムダ式

ラムダ式は無名関数の単純な実装であり、その目的は、関数、特に多様なセット計算関数の定義を単純化することです。Kotlin は Lambda 式をサポートしていますが、コンパイル言語の関係上、簡単にパラメーター式を値パラメーターまたは関数パラメーターとして指定することは難しく、それらを区別するために複雑なインターフェース規則しか設計できず、いわゆる専用インターフェースと呼ばれるものさえあります。これにより、Kotin の Lambda 式は記述が難しくなり、データ処理の専門性に欠けます。いくつかの例:

"abcd".substring( 1,2)						//值参数
"abcd".sumBy{ it.toInt()}					//函数参数
mData.forEachIndexed{ index,it-> if(index>0) it.Mom=…}		//函数参数的函数带多个参数

Koltin の Lambda 式は十分に専門的ではなく、フィールドを使用する場合は構造化データ オブジェクトの変数名 (it) を使用する必要があり、SQL のような単一のテーブルを計算する場合はテーブル名を省略できることも示しています。

Scala の Lambda 式は、コンパイル言語として Kotlin と大差ありません. また、複雑なインターフェイス ルールを設計する必要があり、これも書くのが難しいため、ここでは例を挙げません. 前の期間よりも多く計算する場合は、構造化データ オブジェクトの変数名もフィールドの前に配置するか、mData ("Amount") や col ("Amount") などの col 関数を使用する必要があります。 $"Amount" または 'Amount のように構文糖衣を追加する必要がありますが、多くの関数はこの書き方をサポートしていません。

SPL の Lambda 式はシンプルで使いやすく、インタープリター言語の特性に関連して前の 2 つよりも専門的です。解釈された言語は、値パラメーターと関数パラメーターを簡単に推測できます。高階関数用のいわゆる複雑な特別なインターフェイスはなく、すべての関数インターフェイスは同じように単純です。いくつかの例:

mid("abcd",2,1)							//值参数
Orders.sum(Amount*Amount)					//函数参数
mData.(Mom=Amount/Amount[-1]-1)					//函数参数的函数带多个参数

SPL は、次のような構造化データ オブジェクト変数名なしでフィールド名を直接使用できます。

Orders.select(Amount>1000 && Amount<=3000 && like(Client,"*S*"))

SPL のほとんどのループ関数には、既定のメンバ変数 ~ と序数変数 # があり、特に構造化データの計算では、コード記述の利便性が大幅に向上します。たとえば、偶数の位置にあるレコードを取得するには、次のようにします。

Students.select(# % 2==0)

各グループの上位 3 人を見つける:

Orders.group(SellerId;~.top(3;Amount))

SPL 機能のオプションとレベルのパラメーター

開発効率をさらに向上させるために、SPL には独自の関数構文も用意されています。

似たような機能を持つ関数が多数ある場合、ほとんどのプログラミング言語は異なる名前またはパラメーターでしか区別できず、使用するのに不便です。SPL は非常にユニークな関数オプションを提供するため、同様の関数を持つ関数は関数名を共有し、関数オプションのみを使用して違いを区別できます。たとえば、select 関数の基本機能はフィルター処理ですが、条件に一致する最初のレコードのみをフィルター処理する場合は、オプション @1 を使用できます。

T.select@1(Amount>1000)

二分法で順序付けされたデータを高速にフィルタリングするには、@b を使用します。

T.select@b(Amount>1000)

関数オプションは、次のように組み合わせることもできます。

Orders.select@1b(Amount>1000)

一部の関数のパラメーターは複雑で、複数のレイヤーに分割される場合があります。従来のプログラミング言語には、このための特別な構文スキームがなく、多層構造のデータ オブジェクトを生成して渡すことしかできず、非常に面倒でした。SQL はキーワードを使用してパラメーターを複数のグループに分けます。これはより直感的でシンプルですが、多くのキーワードを使用し、ステートメントの構造に一貫性がなくなります。SPL は、複雑なパラメーターの表現を簡素化するために階層パラメーターを創造的に発明し、セミコロン、コンマ、コロンを使用してパラメーターを上位から下位の 3 つのレイヤーに分割しました。

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

情報源

データソースの種類

Kotlin は原則としてすべての Java データ ソースをサポートできますが、Kotlin にはデータ ソース アクセス インターフェイスが組み込まれておらず、最適化もされていないため、コードが非常に煩雑で、型変換が面倒で、安定性に欠けています。構造化データ処理用 (JDBC インターフェースを除く)。この意味で、データ ソースを直接サポートしておらず、Java サードパーティ クラス ライブラリしか使用できないとも言えますが、幸いなことに、サードパーティ クラス ライブラリの数は十分に多くあります。

Scala は多くの種類のデータ ソースをサポートしており、6 つのデータ ソース インターフェイスが組み込まれており、構造化されたデータ処理用に最適化されています。たとえば、JDBC、CSV、TXT、JSON、Parquet 列ストレージ形式、ORC 列ストレージ形式、その他のデータ ソース インターフェイスは組み込みではなく、コミュニティ グループによって開発されたサードパーティ ライブラリを使用できます。Scala は、構造化されたデータ オブジェクトを出力するためにサードパーティ クラス ライブラリを必要とするデータ ソース インターフェイス仕様を提供します. 一般的なサードパーティ インターフェイスには、XML、Cassandra、HBase、および MongoDB が含まれます。

SPL には、最も組み込みのデータ ソース インターフェイスがあり、次のような構造化データ処理用に最適化されています。

JDBC (つまり、すべての RDB)

CSV、TXT、JSON、XML、エクセル

HBase、HDFS、ハイブ、スパーク

セールスフォース、アリババクラウド

Restful、WebService、Webcrawl

Elasticsearch、MongoDB、Kafka、R2dbc、FTP

Cassandra、DynamoDB、influxDB、Redis、SAP

これらのデータ ソースは直接使用できるため、非常に便利です。リストされていない他のデータ ソースについては、SPL もインターフェイス仕様を提供します.仕様が SPL の構造化されたデータ オブジェクトとして出力される限り、その後の計算を実行できます。

コード比較

正規の CSV ファイルを例として、3 つの言語の解析コードを比較します。コトリン:

val file = File("D:\\data\\Orders.txt")
data class Order(var OrderID: Int,var Client: String,var SellerId: Int, var Amount: Double, var OrderDate: Date)
var sdf = SimpleDateFormat("yyyy-MM-dd")
var Orders=file.readLines().drop(1).map{
var l=it.split("\t")
var r=Order(l[0].toInt(),l[1],l[2].toInt(),l[3].toDouble(),sdf.parse(l[4]))
r
}
var resutl=Orders.filter{
it.Amount>= 1000 && it.Amount < 3000}

Koltin はプロフェッショナリズムに欠けており、通常、CSV を読み取るために、データ構造を事前に定義したり、ループ関数でデータ型を手動で解析したりするなど、コードをハード ライトする必要があります.全体的なコードは非常に面倒です. また、OpenCSV などのクラス ライブラリで読み取ることもできますが、コード内でデータ型を解析する必要はありませんが、構成ファイルで定義する必要があり、実装プロセスは必ずしも単純ではありません。

Scala is professional and has a built-in interface for parsing CSV. コードは Koltin よりもはるかに短いです。

val spark = SparkSession.builder().master("local").getOrCreate()
val Orders = spark.read.option("header", "true").option("sep","\t").option("inferSchema", "true").csv("D:/data/orders.csv").withColumn("OrderDate", col("OrderDate").cast(DateType))
Orders.filter("Amount>1000 and Amount<=3000")

Scala にはデータ型の解析に問題がありますが、それ以外には明らかな欠点はありません。

SPL はより専門的で、分析と計算のための行は 1 つだけです。

T("D:/data/orders.csv").select(Amount>1000 && Amount<=3000)

クロスオリジン コンピューティング

JVM データ処理言語は非常にオープンで、さまざまなデータ ソースを関連付け、マージ、および集約するための十分な機能を備えています。

Kotlin は十分に専門的ではありません. 組み込みのデータ ソース インターフェイスが欠けているだけでなく、クロスソース コンピューティング機能も欠けています. ハード ライティング コードによってのみ実装できます. 従業員テーブルと注文テーブルが異なるデータ ソースから取得されたと仮定して、2 つを関連付けます。

data class OrderNew(var OrderID:Int ,var Client:String, var SellerId:Employee ,var Amount:Double ,var OrderDate:Date )
val result = Orders.map { o->var emp=Employees.firstOrNull{ it.EId==o.SellerId
}
emp?.let{ OrderNew(o.OrderID,o.Client,emp,o.Amount,o.OrderDate)
}
}
.filter {o->o!=null}

Kotlin の短所は分かりやすい.コードが長いと Lambda 式が読みにくくなり, 通常のコードほど分かりにくい. 関連するデータ構造をあらかじめ定義しておく必要がある.柔軟性が低く、問題解決の流暢さに影響します。

Scala は Kotlin よりも専門的で、複数のデータ ソース インターフェースが組み込まれているだけでなく、クロスソース コンピューティングのための機能も提供します。同じ計算で、Scala コードははるかに単純です。

val join=Orders.join(Employees,Orders("SellerId")===Employees("EId"),"Inner")

Scala は、構造化データの計算専用のオブジェクトと関数を備えているだけでなく、Lambda 言語とうまく連携していることがわかります.コードは理解しやすく、事前にデータ構造を定義する必要はありません.

SPL はより専門的であり、構造化データ オブジェクトはより専門的であり、クロスソース コンピューティング関数はより便利であり、コードはより短くなります。

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

独自の保存形式

通常、繰り返し使用される中間データは、フェッチのパフォーマンスを向上させるために、特定の形式でローカル ファイルとして保存されます。Kotlin はさまざまな形式のファイルをサポートし、理論的には中間データを保存して再計算できますが、データ処理の専門家ではないため、基本的な読み取りと書き込み操作には大量のコードを記述する必要があり、独自の保存形式がないことと同じです。 .

Scala はさまざまなストレージ形式をサポートしていますが、中でも parquet ファイルは一般的に使用され、使いやすいものです。Parquet is a open source storage format that supports column storage and can store a large amount of data. 中間計算結果 (DataFrame) は、parquet ファイルとの間で簡単に変換できます。残念ながら、寄木細工のインデックスはまだ成熟していません。

val df = spark.read.parquet("input.parquet")
val result=df.groupBy(data("Dept"),data("Gender")).agg(sum("Amount"),count("*"))
result.write.parquet("output.parquet")

SPL は btx と ctx の 2 つのプライベート バイナリ ストレージ形式をサポートし、btx は単純な行ストレージ、ctx は行ストレージ、列ストレージ、インデックスをサポートし、大量のデータを格納して高性能コンピューティングを実行でき、中間計算結果 (シーケンス テーブル/カーソル)はこれと比較できます。2つのファイルは簡単に相互に変換できます。

1 =file("input.ctx").open()
2 =A1.cursor(Dept,Gender,Amount).groups(Dept,Gender;sum(Amount):amt,count(1):cnt)
3 =file("output.ctx").create(#Dept,#Gender,amt,cnt).append(A2.cursor())

構造化データ コンピューティング

構造化データ オブジェクト

データ処理の中核は計算、特に構造化データの計算です。構造化データ オブジェクトの専門性は、データ処理の利便性を大きく左右します。

Kotlin には専門的な構造化データ オブジェクトがなく、構造化データの計算には List<EntityBean> がよく使用されます。この場合、EntityBean はデータ クラスを使用して定義プロセスを簡素化できます。

List は順序付けられたコレクション (反復可能) であり、Kotlin はメンバー番号とコレクションに関連するすべての関数をサポートします。たとえば、シリアル番号でメンバーにアクセスするには:

Orders[3]						//按下标取记录,从0开始
Orders.take(3)						//前3条记录
Orders.slice(listOf(1,3,5)+IntRange(7,10))		//下标是1、3、5、7-10的记录

逆数でメンバーを取得することもできます。

Orders.reversed().slice(1,3,5)				//倒数第1、3、5条
Orders.take(1)+Orders.takeLast(1)			//第1条和最后1条

順序を含む計算は比較的難しいですが、Kotlin は順序付きカウント セットをサポートしており、関連する計算を実行するのに便利です。List は、コレクションの一種として、コレクション メンバーの追加、削除、変更、交差、分割などの機能を得意としています。しかし、List は専門的な構造化データ オブジェクトではなく、フィールド構造に関連する関数が含まれると、Kotlin での実装は困難になります。たとえば、Orders の 2 つのフィールドを使用して、新しい構造化データ オブジェクトを作成します。

data class CliAmt(var Client: String, var Amount: Double)
var CliAmts=Orders.map{it.let{CliAmt(it.Client,it.Amount) }}

上記の関数は非常に一般的に使用されており、単純な SQL ステートメントの select Client, Amount from Orders と同等ですが、Kotlin を記述するのは非常に面倒で、新しい構造を事前に定義するだけでなく、田畑。フィールドを取得する単純な機能は非常に面倒であり、高度な機能はより面倒です。たとえば、フィールドのシリアル番号による取得、パラメーターによる取得、フィールド名のリストの取得、フィールド構造の変更、フィールドのキーとインデックスの定義、クエリフィールドごとに計算します。

Scala にも List がありますが、これは Kotlin と大差ありませんが、Scala は構造化データ処理用に、より専門的なデータ オブジェクト DataFrame (および RDD、DataSet) を設計しました。
DataFrame は、構造化されたデータ ストリームであり、データベースの結果セットにいくぶん似ています. これは順序付けされていないコレクションであるため、取得する番号の押下をサポートしておらず、偽装してのみ実装できます. たとえば、10 番目のレコード:

Orders.limit(10).tail(1)(0)						

間隔、移動平均、逆ソートなど、順序に関するすべての計算、DataFrame の実装はより面倒であると考えられます。
順序付けられていないデータに加えて、DataFrame は変更 (不変機能) をサポートしていません。データまたは構造を変更する場合は、新しい DataFrame を生成する必要があります。たとえば、フィールド名を変更するには、実際にはレコードをコピーします。

Orders.selectExpr("Client as Cli")					

DataFrame は、セットを組み合わせて重複を削除することでユニオンを実現できる、分割、マージ、クロスマージなどの一般的なセット計算をサポートしていますが、レコードをコピーすることによって実装されるため、セット計算のパフォーマンスは一般的に高くありません。
多くの欠点がありますが、DataFrame は専門的な構造化データ オブジェクトであり、フィールドにアクセスする機能は Kotlin の範囲を超えています。たとえば、メタデータ/フィールド名のリストを取得するには:

Orders.schema.fields.map(it=>it.name).toList

フィールドを使用して数値をフェッチすることも便利です。たとえば、2 つのフィールドをフェッチして新しいデータフレームを形成する場合などです。

Orders.select("Client","Amount")				//可以只用字段名

または、計算された列で新しい DataFrame を形成します。

Orders.select(Orders("Client"),Orders("Amount")+1000)		//不能只用字段名	

残念ながら、DataFrame は文字列形式の名前によるフィールドの参照のみをサポートしており、多くのシナリオで不便なフィールドのシリアル番号やデフォルト名をサポートしていません。さらに、DataFrame はインデックスの定義をサポートしていないため、高性能のランダム クエリを実行できず、プロフェッショナリズムにはまだ欠陥があります。

SPL の構造化データ オブジェクトはシーケンス テーブルであり、十分にプロフェッショナルで、使いやすく、表現力に優れているという利点があります。
シーケンス番号によるメンバーへのアクセス:

Orders(3)							//按下标取记录,从1开始
Orders.to(3)							//前3条记录
Orders.m(1,3,5,7:10)						//序号是1、3、5、7-10的记录

レコードは逆数で取得されます. ユニークな機能は、逆数を示す負号をサポートすることです.これは、Kotlin よりも専門的で便利です:

Orders.m(-1,-3,-5)						//倒数第1,3,5条
Orders.m(1,-1)							//第1条和最后1条

セットの一種として、シーケンス テーブルは、セットのメンバーを追加、削除、変更、交差、マージ、分割、および分割する機能もサポートしています。シーケンス テーブルは List のようなミュータブルなコレクションであるため、コレクションの計算は、レコードをコピーするのではなく、可能な限り空きレコードを使用します。パフォーマンスは Scala よりもはるかに優れており、メモリ使用量も少なくなります。
シーケンス テーブルは、コレクション関連の機能に加えて、専門的な構造化データ オブジェクトであり、さらに重要なことに、フィールドに簡単にアクセスできます。たとえば、フィールド名のリストを取得するには:

Orders.fname()							

2 つのフィールドを使用して、新しいシーケンス テーブルを作成します。

Orders.new(Client,Amount)

計算列を含む新しいシーケンス テーブルを作成します。

Orders.new(Client,Amount*0.2)

フィールド名を変更します。

Orders.alter(;OrderDate)					//不复制记录

In some scenario, you need to access fields with a field numbers or default names. SPL には、対応するアクセス方法が用意されています。

Orders(Client)							//按字段名(表达式取)
Orders([#2,#3])							//按默认字段名取
Orders.field(“Client”)						//按字符串(外部参数)
Orders.field(2)							//按字段序号取

専門的な構造化データ オブジェクトとして、シーケンス テーブルはフィールドのキーとインデックスの定義もサポートしています。

Orders.keys@i(OrderID)						//定义键,同时建立哈希索引
Orders.find(47)							//用索引高速查找

計算機能

Kotlin は、フィルタリング、並べ替え、重複排除、セットのクロスマージ、さまざまな集計、グループ化と要約など、いくつかの基本的な計算機能をサポートしています。ただし、これらの関数はすべて通常のコレクション用であり、計算対象を構造化データ オブジェクトに変更すると、計算関数ライブラリが非常に不足し、通常はハードコーディングで補完して計算を実現します。Kotlin ではサポートされておらず、コーディングによってのみ実装できる基本的な集合操作が多数あります。これらには、関連付け、ウィンドウ関数、ランキング、行から列へ、マージ、二分探索などがあります。その中で、マージと二分探索は順序に関する操作ですが、Kotlin List は順序集合であるため、これらの操作をコーディングで実装することはそれほど難しくありません。一般に、Kotlin の関数ライブラリは、構造化データ コンピューティングに対して弱いと言えます。

Scala のコンピューティング関数は比較的豊富であり、Kotlin でサポートされていない関数 (ランク付け、関連付け、ウィンドウ関数、行から列への関数) を含め、すべて構造化データ オブジェクト用に設計されていますが、基本的に SQL のフレームワークを超えていません。また、Scala でサポートされていない基本的な集合操作、特にマージやバイナリ検索などの順序に関連するものもあります.Scala DataFrame は SQL でデータ無秩序の概念を使用しているため、そのような操作を実装することは非常に困難です.自分でコーディングします。一般に、Scala の関数ライブラリは Kotlin よりも豊富ですが、基本的な操作はまだ不足しています。

SPL は計算機能が最も豊富であり, それらはすべて構造化データ オブジェクト用に設計されています. SPL は構造化データ操作の内容を大幅に充実させ, SQL を超えた多くの内容を設計します. もちろん, Scala/Kotlin が行う機能でもあります.順序付けされた計算などはサポートされていません: マージ、バイナリ検索、間隔ごとのレコード、適格なレコードのシーケンス番号; 通常の同等のグループ化に加えて、列挙型グループ化、アライメント グループ化、および順序付きグループ化もサポートされています; アソシエーション タイプは外部キーに分割されます主キーは、データを制約するためにサポートされ、高速クエリのためのインデックスをサポートし、マルチレベル データ (マルチテーブル アソシエーションまたは Json\XML) のための再帰クエリなどをサポートします。

グループ化を例にとると、通常の同等のグループ化に加えて、SPL はさらに多くのグループ化スキームも提供します。

列挙グループ化: グループ化は複数の条件式に基づいており、同じ条件を満たすレコードがグループにまとめられます。

整列グループ化: グループ化は外部セットに基づいています. フィールド値がセットのメンバーと等しいレコードは、グループにグループ化されます. グループの順序は、セットのメンバーの順序と一致しています. 空グループは許可されます。このコレクションに属するレコード」.

順序付けられたグループ化: グループ化は、すでに順序付けられたフィールドに基づいています. たとえば、フィールドが変更されるか、特定の条件が確立されると、新しいグループが作成されます. SPL は、このような順序付けられたグループ化を直接提供します。グループ化機能. 非常にシンプルで、計算パフォーマンスが向上します. 他の言語 (SQL を含む) にはこのグループ化がなく、骨の折れる従来の同等のグループ化に変換するか、自分でハードコーディングするしかありません。

これら 3 つの言語が関数を計算する方法の違いを理解するために、いくつかの一般的な例を見てみましょう。

選別

顧客順、金額の逆順で並べ替えます。コトリン:

Orders.sortedBy{it.Amount}.sortedByDescending{it.Client}

Kotlin コードは長くはありませんが、逆順と正順は別の関数である、フィールド名にテーブル名を含める必要がある、コードに記述されているフィールドの順序が実際の並べ替えとは逆である、などの不都合があります。注文。

スカラ:

Orders.orderBy(Orders("Client"),-Orders("Amount"))

Scala はもっと単純で、マイナス記号は逆の順序を表し、コードによって記述されたフィールドの順序はソート順と同じです。残念ながら、フィールドには依然としてテーブル名が必要です; コンパイルされた言語は文字列を使用して式の動的解析を実装することしかできないため、コード スタイルに一貫性がなくなります。

SPL:

Orders.sort(Client,-Amount)

SPL コードはより単純で、フィールドにテーブル名を付ける必要がなく、解釈された言語コード スタイルを簡単に統一できます。

グループ概要

コトリン:

data class Grp(var Dept:String,var Gender:String) 
data class Agg(var sumAmount: Double,var rowCount:Int)
var result1=data.groupingBy{Grp(it!!.Dept,it.Gender)}
.fold(Agg(0.0,0),{acc, elem -> Agg(acc.sumAmount + elem!!.Amount,acc.rowCount+1)})
.toSortedMap(compareBy<Grp> { it.Dept }.thenBy { it.Gender })

Kotlin コードは煩雑で、groupingBy 関数と fold 関数を使用するだけでなく、グループ化と要約を実現するためのハードコーディングも必要です。新しいデータ構造が出現した場合、グループ化された 2 フィールド構造や集約された 2 フィールド構造など、使用する前に事前に定義する必要があります。これは、柔軟性が低いだけでなく、問題解決の流暢さに影響を与えます。 . 最終的な並べ替えは、他の言語での結果の順序と一致させるためのものであり、必須ではありません。

スカラ:

val result=data.groupBy(data("Dept"),data("Gender")).agg(sum("Amount"),count("*"))

Scala コードははるかに単純で、理解しやすいだけでなく、事前にデータ構造を定義する必要もありません。

SPL:

data.groups(Dept,Gender;sum(Amount),count(1))

SPL コードは最も単純で、その表現力は SQL に劣りません。

連想コンピューティング

2 つのテーブルに同じ名前のフィールドがあり、これらは関連付けられてグループ化されています。コトリンコード:

data class OrderNew(var OrderID:Int ,var Client:String, var SellerId:Employee ,var Amount:Double ,var OrderDate:Date )
val result = Orders.map { o->var emp=Employees.firstOrNull{it.EId==o.EId}
emp?.let{ OrderNew(o.OrderID,o.Client,emp,o.Amount,o.OrderDate)}
}
.filter {o->o!=null}
data class Grp(var Dept:String,var Gender:String) 
data class Agg(var sumAmount: Double,var rowCount:Int)
var result1=data.groupingBy{Grp(it!!.EId.Dept,it.EId.Gender)}
.fold(Agg(0.0,0),{acc, elem -> Agg(acc.sumAmount + elem!!.Amount,acc.rowCount+1)})
.toSortedMap(compareBy<Grp> { it.Dept }.thenBy { it.Gender })

Kotlin コードは扱いにくく、関連付け結果、グループ化された 2 フィールド構造、集約された 2 フィールド構造など、多くの場所で新しいデータ構造を定義する必要があります。

スカラ

val join=Orders.as("o").join(Employees.as("e"),Orders("EId")===Employees("EId"),"Inner")
val result= join.groupBy(join("e.Dept"), join("e.Gender")).agg(sum("o.Amount"),count("*"))

Scala は、面倒なデータ構造の定義やハードコーディングがなく、Kolin よりもはるかに単純です。

SPL はより単純です。

join(Orders:o,SellerId;Employees:e,EId).groups(e.Dept,e.Gender;sum(o.Amount),count(1))

包括的なデータ処理の比較

CSV の内容は標準化されていません.3 行ごとに 1 つのレコードに対応し、2 行目には 3 つのフィールド (つまり、コレクションのコレクション) が含まれています.ファイルは標準化された構造化データ オブジェクトに編成され、3 番目でソートされますそして4番目のフィールド。

コトリン:

data class Order(var OrderID: Int,var Client: String,var SellerId: Int, var Amount: Double, var OrderDate: Date)
var Orders=ArrayList<Order>()
var sdf = SimpleDateFormat("yyyy-MM-dd")
var raw=File("d:\\threelines.txt").readLines()
raw.forEachIndexed{index,it->
if(index % 3==0) {
var f234=raw[index+1].split("\t")
var r=Order(raw[index].toInt(),f234[0],f234[1].toInt(),f234[2].toDouble(),
sdf.parse(raw[index+2]))
Orders.add(r)
}
}
var result=Orders.sortedByDescending{it.Amount}.sortedBy{it.SellerId}

Koltin はデータ処理の専門家ではありません。ほとんどの関数は、位置によるフィールドの取得やコレクションのコレクションからのフィールドの取得など、ハードコーディングされたコードを必要とします。

スカラ:

val raw=spark.read.text("D:/threelines.txt")
val rawrn=raw.withColumn("rn", monotonically_increasing_id())
var f1=rawrn.filter("rn % 3==0").withColumnRenamed("value","OrderId")
var f5=rawrn.filter("rn % 3==2").withColumnRenamed("value","OrderDate")
var f234=rawrn.filter("rn % 3==1")
.withColumn("splited",split(col("value"),"\t"))
.select(col("splited").getItem(0).as("Client")
,col("splited").getItem(1).as("SellerId")
,col("splited").getItem(2).as("Amount"))
f1.withColumn("rn1",monotonically_increasing_id())
f5=f5.withColumn("rn1",monotonically_increasing_id())
f234=f234.withColumn("rn1",monotonically_increasing_id())
var f=f1.join(f234,f1("rn1")===f234("rn1"))
.join(f5,f1("rn1")===f5("rn1"))
.select("OrderId","Client","SellerId","Amount","OrderDate")
val result=f.orderBy(col("SellerId"),-col("Amount"))

Scala はデータ処理により特化しており、ハードライティングのループ コードではなく、構造化された計算関数を多用しています。ただし、Scala には順序付けられた計算の機能がなく、関連する関数は通常、シーケンス番号の列を追加して処理する必要があり、全体のコードが長くなります。
SPL:

1 =file("D:\\data.csv").import@si()
2 =A1.group((#-1)\3)
3 =A2.new(~(1):OrderID, (line=~(2).array("\t"))(1):Client,line(2):SellerId,line(3):Amount,~( 3):注文日)
4 =A3.sort(SellerId,-Amount)

SPL はデータ処理において最もプロフェッショナルであり、構造化された計算関数のみで目標を達成できます。SPL は順序付けられた計算をサポートしています, you can directly group by position, take fields by position, and take fields from collections in collection. 実装の考え方は Scala に似ていますが、コードははるかに短くなります。

アプリケーションの構造

Java アプリケーションの統合

Kotlin はバイトコードにコンパイルされ、通常のクラス ファイルと同様に、Java から簡単に呼び出すことができます。たとえば、KotlinFile.kt の静的メソッド fun multiLines(): List<Order> は Java によって正しく認識され、直接呼び出すことができます。

java.util.List result=KotlinFileKt.multiLines();
result.forEach(e->{System.out.println(e);});

Scala もコンパイル後のバイトコードであり、Java からも簡単に呼び出すことができます。たとえば、ScalaObject オブジェクトの静的メソッド def multiLines():DataFrame は、Java によって Dataset タイプとして認識され、少し変更して呼び出すことができます。

org.apache.spark.sql.Dataset df=ScalaObject.multiLines();
df.show();

SPL は共通の JDBC インターフェースを提供し、単純な SPL コードを SQL のように Java に直接埋め込むことができます。

Class.forName("com.esproc.jdbc.InternalDriver");
Connection connection =DriverManager.getConnection("jdbc:esproc:local://");
Statement statement = connection.createStatement();
String str="=T(\"D:/Orders.xls\").select(Amount>1000 && Amount<=3000 && like(Client,\"*s*\"))";
ResultSet result = statement.executeQuery(str);

複雑な SPL コードは、最初にスクリプト ファイルとして格納し、次に Java によってストアド プロシージャの形式で呼び出すことができます。これにより、計算コードとフロントエンド アプリケーションの間の結合を効果的に減らすことができます。

Class.forName("com.esproc.jdbc.InternalDriver");
Connection conn =DriverManager.getConnection("jdbc:esproc:local://");
CallableStatement statement = conn.prepareCall("{call scriptFileName(?, ?)}");
statement.setObject(1, "2020-01-01");
statement.setObject(2, "2020-01-31");
statement.execute();

SPLはインタープリター型言語であり、修正後はコンパイルせずに直接実行でき、コードのホットスイッチングに対応しているため、メンテナンスの負担が軽減され、システムの安定性が向上します。Kotlin と Scala はコンパイル済み言語であり、コンパイル後にアプリケーションを再起動する必要があります。

オープンソースはすべてのプログラマーの精神であり、誰もがコミュニケーションを取り、一緒に学ぶことができます

対話型コマンド ライン

Kotlin の対話型コマンド ラインには、Kotlinc コマンドを使用して開始される追加のダウンロードが必要です。Kotlin コマンド ラインは、理論的には任意の複雑なデータ処理を実行できますが、コードは一般に長く、コマンド ラインで変更するのが難しいため、単純な数値計算に適しています。

>>>Math.sqrt(5.0)
2.236.6797749979

Scala の対話型コマンド ラインは組み込みで、同じ名前のコマンドで起動されます。Scala コマンド ラインは理論的にはデータ処理を実行できますが、コードが比較的長いため、単純な数値計算に適しています。

scala>100*3
rest1: Int=300

SPL には、"esprocx -r -c" コマンドで始まる対話型コマンド ラインが組み込まれています。通常、SPL コードは短く、コマンド ラインでの簡単なデータ操作が可能です。

(1): T("d:/Orders.txt").groups(SellerId;sum(Amount):amt).select(amt>2000)
(2):^C
D:\raqsoft64\esProc\bin>Log level:INFO
1       4263.900000000001
3       7624.599999999999
4       14128.599999999999
5       26942.4

SPL情報

データベースは私たちの使用においてますます重要になってきています. さまざまな比較を通じて、アプリケーション開発における一般的なデータ処理タスクについては、Kotlin は十分に専門的ではないため開発効率が低く、Scala は一定の専門性と開発効率を備えていることがわかります. Kotlin、しかし SPL ほどではありません。SPL は、より簡潔な構文、より高い表現効率、より多くの種類のデータ ソース、より簡単なインターフェイス、より専門的な構造化データ オブジェクト、より豊富な機能とより強力な計算能力、およびはるかに効率的な開発を備えています。そしてスカラ。

交換留学を歓迎します。

おすすめ

転載: blog.csdn.net/mengchuan6666/article/details/126616736