Sqoop1.3.0のSQL関連ソース(内部実装)について。
import時にテーブル名を指定するとConnManager#importTable()、SQLを指定するとConnManager#importQuery()が呼ばれる。
ここではSqoopのSQLがどうなっているかを調べたいので、importTable()を追っていく。
Manager | ImportJob | Mapper | InputFormat | |
---|---|---|---|---|
デフォルト | SqlManager | DataDrivenImportJob | TextImportMapper SequenceFileImportMapper AvroImportMapper |
DataDrivenDBInputFormat |
MySQL | MySQLManager | |||
DirectMySQLManager | MySQLDumpImportJob | MySQLDumpMapper | MySQLDumpInputFormat | |
PostgreSQL | PostgresqlManager | |||
DirectPostgresqlManager | - | - | - | |
HSQLDB | HsqldbManager | |||
Oracle | OracleManager | OracleDataDrivenDBInputFormat | ||
SQLServer | SQLServerManager | |||
DB2 | Db2Manager |
空欄は、デフォルトのクラスを使用していることを意味する。
importのデフォルトのInputFormat。
Oracle以外
SELECT カラム名,… FROM テーブル名 AS テーブル名 WHERE (条件) AND (分割カラム >= 最小値 AND 分割カラム < 最大値)
Oracle
SELECT カラム名,… FROM テーブル名 WHERE (条件) AND (分割カラム >= 最小値 AND 分割カラム < 最大値)
最小値・最大値はカラムのデータ型に応じてTextSplitterやDateSplitter等で決められる。
MySQLのimportのダイレクトモード用Mapper。
データ分割方法は通常と同じだが、テーブルの読み込みは(SQLでなく)mysqldumpコマンドを使用する。
各Mapタスクでmysqldumpを実行して標準出力にデータを出力し、パイプで受け取ってMapperの出力としている。
PostgreSQLのimportのダイレクトモードはMapReduceを使わずに動作する。
psqlコマンドでCOPY文を実行する。
(sqoopコマンドのオプションで指定して場合はQUOTEやESCAPEの文字もCOPY文に指定される)
COPY (SELECT カラム名,… FROM テーブル名 WHERE 条件) TO STDOUT WITH DELIMITER E'\054' CSV;
このCOPY文の結果は標準出力に出力されるので、それをパイプで受け取ってHDFS上のファイルに書き込んでいる。
Oracle独自のデータ型があるからその処理を記述しているだけで、SQLとしてはDataDrivenDBInputFormatと同じ。
Manager | ExportJob | Mapper | OutputFormat | |
---|---|---|---|---|
デフォルト | SqlManager | JdbcExportJob | TextExportMapper SequenceFileExportMapper AvroExportMapper |
バッチ以外…ExportOutputFormat バッチモード…ExportBatchOutputFormat |
MySQL | MySQLManager | |||
DirectMySQLManager | MySQLExportJob | MySQLTextExportMapper MySQLRecordExportMapper |
NullOutputFormat | |
PostgreSQL | PostgresqlManager | |||
DirectPostgresqlManager | ||||
HSQLDB | HsqldbManager | |||
Oracle | OracleManager | JdbcExportJob | ExportBatchOutputFormat | |
SQLServer | SQLServerManager | JdbcExportJob | ExportBatchOutputFormat | |
DB2 | Db2Manager | JdbcExportJob | ExportBatchOutputFormat |
空欄は、デフォルトのクラスを使用していることを意味する。
PostgreSQLのexportはダイレクトモードに対応していないので、DirectPostgresqlManagerでも特別な処理は無い。
Oracle・SQLServer・DB2はマルチインサートの構文が無い(そして代替方式の実行効率が悪い?)為か、デフォルトモードでもバッチモードと同じ処理方式になる(ExportBatchOutputFormatが使われる)ようだ。
exportのデフォルトのOutputFormat。
(全てのRDBMSのデフォルトモードでこのOutputFormatが使われるわけではなく、ものによってはExportBatchOutputFormatが使われる)
INSERT INTO テーブル名 VALUES(?,…,?), (?,…,?), 〜, (?,…,?)
マルチインサート。
VALUESの後ろに複数のレコードを記述する方式。
JDBCのPrepareStatementのaddBatch()・executeBatch()を使う方式。
基本的にはバッチモード(--batch)を指定すると このOutputFormatが使われるが、RDBMSの種類によってはデフォルトで使われる。
INSERT INTO テーブル名 VALUES(?,…,?)
INSERT文自体は1レコードずつ書き込むタイプ。
MySQLのexportのダイレクトモード用Mapper。
実際にはMySQLExportMapperを継承したクラス(CSVファイルの場合はMySQLTextExportMapper、SequenceFileの場合はMySQLRecordExportMapper)が使われる。
各MapタスクでHDFSの内容をローカルファイルに書き出し、それをmysqlimportコマンドで読み込んでテーブルに書き込む。
(このローカルファイルに対しては、非同期で書き込み・読み込みを行う)
Oracleにはマルチインサートの構文が無いので、代わりのSQLが用意されている。
が、実際には使われていないようだ。
INSERT INTO テーブル名 SELECT ?,…,? FROM DUAL UNION ALL SELECT ?,…,? FROM DUAL UNION ALL 〜 SELECT ?,…,? FROM DUAL
たぶんOracleと同様に、マルチインサートの構文が無いので代わりのSQLを用意しているのだと思う。
これも実際には使われていないようだ。
INSERT INTO テーブル名 SELECT ?,…,? UNION ALL SELECT ?,…,? UNION ALL 〜 SELECT ?,…,?