Spark SQLによる値のハッシュ化を試してみた

GlueのSparkジョブに関連してSpark SQLによる値のハッシュ化について調べてみました。
2019.08.28

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは。DA事業本部の大高です。

GlueのSparkジョブに関連してSpark SQLによる値のハッシュ化について調べてみました。

前提

Spark SQLを利用するにあたって以下の記事を参考にpysparkをMacの環境にインストールしています。また、インストールしたバージョンは 2.4.3 になります。

MacのローカルでPySparkをJupyterNotebookから使う

利用できるハッシュ化関数はどのようなものがあるか

調査したところ、以下の4つのハッシュ化関数が利用できそうでした。

試してみた

ということで、それぞれ実際に試してみました。

まずは、サンプル用ファイルを以下のように用意します。

/tmp/sample.csv

id,name,score
1,Jack,20
2,Jhon,30
3,Blue,80
4,Red,70
5,Yellow,40

用意したらpysparkを起動して、データをデータフレームに読み込んでから、テーブルとして利用できるようにします。

# データフレームにファイルを読み込む
df = spark.read.csv("/tmp/sample.csv", header=True)
df.show()
+---+------+-----+
| id|  name|score|
+---+------+-----+
|  1|  Jack|   20|
|  2|  Jhon|   30|
|  3|  Blue|   80|
|  4|   Red|   70|
|  5|Yellow|   40|
+---+------+-----+

# このデータフレームに対応するテーブル名を設定
df.createOrReplaceTempView('users')

これで、読み込んだデータは users テーブルとして利用できるようになりました。それぞれSpark SQL内でハッシュ化関数を利用して name を変換した場合、以下のようになりました。

df_md5  = spark.sql("select id, md5(name)       as  md5_name, score from users where id <= 3")
df_sha  = spark.sql("select id, sha(name)       as  sha_name, score from users where id <= 3")
df_sha1 = spark.sql("select id, sha1(name)      as sha1_name, score from users where id <= 3")
df_sha2 = spark.sql("select id, sha2(name, 256) as sha2_name, score from users where id <= 3")

df_md5.show(truncate=False)
+---+--------------------------------+-----+
|id |md5_name                        |score|
+---+--------------------------------+-----+
|1  |40687c8206d15373954d8b27c6724f62|20   |
|2  |3fd53d3362429cd8e00c7d9dfaa30599|30   |
|3  |9594eec95be70e7b1710f730fdda33d9|80   |
+---+--------------------------------+-----+

df_sha.show(truncate=False)
+---+----------------------------------------+-----+
|id |sha_name                                |score|
+---+----------------------------------------+-----+
|1  |bc5351ffae3efe8067951f5deba4b294bf863f86|20   |
|2  |b13b42158655f36814f3c4541c6457f7cad0f719|30   |
|3  |7d44bc449c2a26374800a503f10f3d8949505f40|80   |
+---+----------------------------------------+-----+

df_sha1.show(truncate=False)
+---+----------------------------------------+-----+
|id |sha1_name                               |score|
+---+----------------------------------------+-----+
|1  |bc5351ffae3efe8067951f5deba4b294bf863f86|20   |
|2  |b13b42158655f36814f3c4541c6457f7cad0f719|30   |
|3  |7d44bc449c2a26374800a503f10f3d8949505f40|80   |
+---+----------------------------------------+-----+

df_sha2.show(truncate=False)
+---+----------------------------------------------------------------+-----+
|id |sha2_name                                                       |score|
+---+----------------------------------------------------------------+-----+
|1  |b5fd03dd91df1cfbd2f19c115d24d58bbda01a23fb01924bb78b2cc14f7ff1cb|20   |
|2  |ee0ace6e8f5dc17dc271cb6e7c0cdc2de39f84c84541461b95ed7c59414becf0|30   |
|3  |ec7d56a01607001e6401366417c5e2eb00ffa0df17ca1a9a831e0b32c8f11bf7|80   |
+---+----------------------------------------------------------------+-----+

ドキュメントにも記載の通り、 shasha1 と同じです。

sha(expr) - Returns a sha1 hash value as a hex string of the expr.

また、sha2 の引数である bitLength224256384512が対応しています。それぞれ以下のようになりました。(224256から切り捨てているためか、ちょっと表示がおかしいようです)

>>> df_sha2 = spark.sql("select id, sha2(name, 224) as sha2_name, score from users where id <= 3")
>>> df_sha2.show(truncate=False)
+---+----------------------------+-----+
|id |sha2_name                   |score|
+---+----------------------------+-----+
|1  |ڗBM���cB�p�����B��
Ed�p |20   |
|2  |}OUvѮ�9)쵃�a]<���^�x
J0�  |30   |
|3  |�rb�����c������.g�G��OW|80   |
+---+----------------------------+-----+

>>> df_sha2 = spark.sql("select id, sha2(name, 256) as sha2_name, score from users where id <= 3")
>>> df_sha2.show(truncate=False)
+---+----------------------------------------------------------------+-----+
|id |sha2_name                                                       |score|
+---+----------------------------------------------------------------+-----+
|1  |b5fd03dd91df1cfbd2f19c115d24d58bbda01a23fb01924bb78b2cc14f7ff1cb|20   |
|2  |ee0ace6e8f5dc17dc271cb6e7c0cdc2de39f84c84541461b95ed7c59414becf0|30   |
|3  |ec7d56a01607001e6401366417c5e2eb00ffa0df17ca1a9a831e0b32c8f11bf7|80   |
+---+----------------------------------------------------------------+-----+

>>> df_sha2 = spark.sql("select id, sha2(name, 384) as sha2_name, score from users where id <= 3")
>>> df_sha2.show(truncate=False)
+---+------------------------------------------------------------------------------------------------+-----+
|id |sha2_name                                                                                       |score|
+---+------------------------------------------------------------------------------------------------+-----+
|1  |3fc6ba5a30e729e282e4db3fb5319be2be877b9467787034c6494ff22a38c14341748a58cd3fb099c4f3ea06970e157f|20   |
|2  |046bb737c0ce706d025a391487818318e9d906511df110baa839def4f2bff1c4a38ff721786ad25c8acc3544781ba373|30   |
|3  |f19611ca41a7d6c0985b6f725d3dbd1b120db33a73320499accb564bd58ffdaf0d8fa837c1a68c38742d688769645eac|80   |
+---+------------------------------------------------------------------------------------------------+-----+

>>> df_sha2 = spark.sql("select id, sha2(name, 512) as sha2_name, score from users where id <= 3")
>>> df_sha2.show(truncate=False)
+---+--------------------------------------------------------------------------------------------------------------------------------+-----+
|id |sha2_name                                                                                                                       |score|
+---+--------------------------------------------------------------------------------------------------------------------------------+-----+
|1  |e88b6480dff1a6438c0a5921d12fb85bebfda0f2d6f221272b405672bbe888ec872254fbe57ec0bb0fa34ac265f078950a8e483818f360acdaf344989e7cff26|20   |
|2  |d350cd4f7bfca71445d4c27f4ae51eb3f19ddbe959cdb7df2593506c3b7d2f2bc4e12f9d44b2664c4891dfacd74c2533931ccc52524278c78bb486eb54ebfd5f|30   |
|3  |936b49f641410483ac946a9f62e6881318b2102e114719e4b629e90c57024d83900685223848871d7b37c9a3a80b2a7c7dd4de3730ec2d4919e8430275ae19c3|80   |
+---+--------------------------------------------------------------------------------------------------------------------------------+-----+

また、試しに8を指定したところ以下のようにnullとなってしまいました。

>>> df_sha2 = spark.sql("select id, sha2(name, 8) as sha2_name, score from users where id <= 3")
>>> df_sha2.show(truncate=False)
+---+---------+-----+
|id |sha2_name|score|
+---+---------+-----+
|1  |null     |20   |
|2  |null     |30   |
|3  |null     |80   |
+---+---------+-----+

まとめ

クエリベースで用意されている関数を色々利用できるのは便利ですね。そのほかにもSpark SQLで用意されている関数があるのでうまく活用すると便利そうだと思いました。

どなたかのお役に立てば幸いです。それでは!