X

Big Data、Data Integration、Data Lakeに関するテクノロジー、製品・サービス情報、セミナー情報などをお届けします

Big Data SQL - 処理のオフロード(Smart Scan)

前回の投稿:Big Data SQLをはじめよう - Introduction や、 One Fast Query All your Dataを読んで、Big Data SQLがOracle Databaseを通してHadoop上のデータにクエリを実行することが出来る、ということが理解できたことでしょう。しかし、ただ単にデータをREADしているだけではありません。Big Data SQLは、HDFS上に格納されたデータを処理して、クエリに必要なデータだけをDatabaseに返すことができます。(Exadataに詳しい方にはよく知られた「Smart Scan」することができます)

Oracle DatabaseとHadoopを含むデータマネージメントシステムを想像してみましょう。

Engineered Systemである、Big Data ApplianceとExadataで、Big Data SQLを実行すると、アーキテクチャーは次の図のようになります。

それぞれの優位性は:

  1. データベースの良いところ
    1. トランザクショナルなワークロード
    2. 同時実行性(read/write)
    3. クリティカルなデータの格納
    4. 複数テーブルの結合、複雑なクエリ
  2. Hadoopの良いところ
    1. バッチ処理。同時実行ではないワークロード
    2. 比較的シンプルなクエリ
    3. シンプルなクエリに対するスケーラビリティ
    4. 非構造化データ、半構造化データ(semi-structured data)の扱い

従って、RawデータをHadoop層に格納し、基本的なジョブを処理した後に、準備できたクリーンなデータをデータベース層に持つようなシステムが良さそうです。Big Data SQLは、これを実にシンプルに成し遂げることができます。

Hadoop層では以下のように動作します。

  • データのDeserialization (シリアライズ化されたものを元に戻す)。もしシリアライズ化されたフォーマット(AVRO, JSON, Parquetなど)で格納している場合、デシリアライズ化を行う
  • 列のプルーニング。400列あるテーブルに、クエリでは1列をSELECTする場合、Big Data SQLは399列をプルーニング(除外)して1列だけを返す

  • データ型の変換。データ型を型変換する処理はそれなりに負荷がかかる処理ですが、Big Data SQLは、Oracle Databaseフォーマットへの変換をHadoop層で行う
  • 関数の適用。もしクエリにフィルタpredicate (like “id=…” のようなWhere句の条件指定)があれば、Hadoop層で動く。Hadoop層で動く全ての関数のリストは以下で確認できます(Oracle Database上で実行します)
SQL> SELECT * FROM v$sqlfn_metadata WHERE offloadable = 'YES';

ここからは、”OFFLOADABLE”なクエリ(Hadoop層でワークロードの大半が行われるようなクエリ)を実行することにします。前回の投稿:Big Data SQLをはじめよう - Introduction のクエリを見てみましょう。

SQL> SELECT min(w.ws_sold_time_sk)
FROM WEB_SALES w
WHERE w.ws_sold_date_sk = 2451047;

Big Data SQLの側面からは、フィルタリング(Where句での条件指定)がこのクエリの主要部分です。不要な行を取り除き、適切な行だけをRDBMS側に転送します。更に、Big Data SQLは列のプルーニングも行います。これはテーブルの全列から、これから計算しようとしている列のみを転送することを意味します。実行計画とクエリ統計をEnterprise Managerのから見てみましょう。(Enterprise Managerの「SQL監視」を使用します)

Enterprise Managerからはオフロード効率も確認することができます。

Enterprise Managerの代わりに、実行時の統計を以下のクエリでも確認できます (SQL DeveloperやSQL*Plusなど任意のツールから、ユーザクエリを実行後に実行します)

SQL> SELECT n.name, round(s.value/1024/1024)
FROM v$mystat s, v$statname n
WHERE s.statistic# IN (462,463)
AND s.statistic# = n.statistic#;

cell XT granule bytes requested for predicate offload 32768
cell interconnect bytes returned by XT smart scan     32

これはBig Data SQLにとって良いクエリの典型的な例です。

オフロードが起きるかどうかは、どうやって決まる?

この問いに答える前に、オフロードがどのように動作するかをもう少し詳しく説明します。

最初のステップで、Big Data SQLはストレージインデックスを適用してHDFSからデータをREADし、デシリアライズを行います。実際には、“External Table Service” はデータのREADにCとJavaの2つのモードがあり、テーブル定義にて、アクセスパラメータの設定で指定しています。

…
ACCESS PARAMETERS
( com.oracle.bigdata.datamode=java
)
or
…
ACCESS PARAMETERS
( com.oracle.bigdata.datamode=c
)

Cモードはそれが利用可能な場合に使用します(全てのデータフォーマットに対応しているわけではありません)。どちらの場合も、Big Data SQLはHDFSブロックをREADし、それをOracleフォーマットに変換し(後のスマートスキャン・サブコンポーネントで必要)、スマートスキャンに送ります。スマートスキャンレベルでは、Big Data SQLは列のプルーニング、フィルタリング(行のプルーニング)、JSONやXMLのパースを行います。処理後のデータは、Oracle Databaseに、Oracle Databaseフォーマットで転送されます。

クエリがオフロードされているかどうか、どのように調べればよいでしょうか?これを確認する最初のステップは、Enterprise Managerから待機イベントを見ることです。

オフロード可能なProperクエリの例で見てみましょう(ここでは “Proper”と呼ぶことにします、なぜならワークロードの多くの部分をストレージ側(Hadoopサイド)で実行できるから)。

SQL> SELECT fnull(MIN(WS_SOLD_DATE_SK)), fnull(MIN(WS_NET_PROFIT))
FROM WEB_SALES;

クエリで使用している fnull()は、何もしないPL/SQLファンクションです。(値を受けてそのまま返す)

SQL> create or replace function fnull(input number) return number is
Result number;
begin
  Result:=input;
  return(Result);
end fnull;

WEB_SALES表は多くの列(34列)を持つが、上のクエリでは2列のみが含まれます。MINファンクションはOFFLOADABLEなので、これはHadoopサイドで実行できることを意味します。

SQL> SELECT NAME, offloadable, AGGREGATE
FROM v$sqlfn_metadata
WHERE NAME = 'MIN'
AND AGGREGATE='YES';

NAME offloadable AGGREGATE
---- ----------- ---------
MIN  YES         YES

その結果、Big Data SQLによりフィルターされ、結果がDatabaseサイドに転送された後、Databaseサイドで作成したPL/SQLファンクションが適用されます。Enterprise Managerで見てみましょう。

待機イベントの87%が ”User IO” でこのIOの全てがCell側です(“cell external table smart scan”)。待機イベントの13%はCPU waitsです(おそらくPL/SQL実行の待機)。オフロード統計をチェックすることも有用です。Enterprise Managerで以下のように確認できます。

代わりに、以下のクエリを実行することでも確認できます。

SQL> SELECT n.name, round(s.value/1024/1024)
FROM v$mystat s, v$statname n
WHERE s.statistic# IN (462,463)
AND s.statistic# = n.statistic#;

上の例で、オフロード可能なクエリ、Big Data SQLにとって良いクエリを見てきました。一方で、アンチパターンとなるクエリとして、先の自作したPL/SQLファンクションの適用順を、以下のように逆にしてみます。

SQL> SELECT MIN(fnull(WS_SOLD_DATE_SK)), MIN(fnull(WS_NET_PROFIT))
FROM WEB_SALES;

これは前のクエリと非常に似ており、結果も同じです。しかし、実行状況は全く異なります。列をPL/SQLでラップすると、とたんに、全てのデータをデータベース層に転送しなければならなくなります(PL/SQLはHadoop層では処理されないため)。Enterprise Managerは先の実行例とは異なる待機イベントを示します。

CPU Waitのみが待機イベントとして表示されることが観察できます。クエリの詳細をクリックすると、スマートスキャンの結果すべての行を返している(Eligible bytesの全てがFiltered bytesになってしまっている)ことが分かります。

このケースを可能な限り避け、クエリの大部分を可能な限りHadoop層で行われるように試みましょう。

とはいえ、このクエリでも、Hadoop層でいくつかの仕事は行っています。HDFSブロックをOracle Databaseフォーマットに変換することと、クエリに使用しない列のプルーニングです。

データベースサイドのデータ型変換

もしいくつかのノードでBig Data SQLエージェントが使用不可の場合、どのようになるでしょうか。Cloudera Managerから、Big Data SQLエージェントを停止してみます。

停止後、任意のクエリを実行します。

SQL> SELECT COUNT(1)
FROM STORE_SALES ss
WHERE ss.ss_sold_date_sk = 2452200;

オフロードが行われていない、最初のサインは、クエリが遅くなることです。Enterprise Managerでは、待機イベント “Application: External Procedure Call” が多く見受けられます。

更に、データベース側の、ネットワーク使用状況からも、確認できます。

Big Data SQLの制約

  1. Big Data SQLは、全てのOracle Database SQLです。詳細はここで確認できます。
  2. 全ての関数が、Hadoop層で処理されるわけではありません。オフロード可能な関数は以下のv$ビューで確認できます
    SQL> SELECT NAME FROM v$sqlfn_metadata WHERE offloadable ='YES';
  3. オフロード不可の関数でも、Big Data SQLは列のプルーニングやデータ型変換を行います(それはデータベース層の多くのリソースを節約するのに役立ちます)
  4. 他の処理(オフロード不可の関数)は、データベースサイドで処理されます

本投稿はBig Data SQL Quick Start. Offloading - Part2.を元に投稿しています。

 

Be the first to comment

Comments ( 0 )
Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.