プロセスデータのソースは.sparksqlを読み取ります
1.spark現在、読書JDBC、ハイブ、テキスト、オークや他の種類のデータをサポートすることがHBaseのか、他のデータソースをサポートするためであれば、あなたがカスタマイズする必要があります
2.読み取り処理
(1)sparksql进行session.read.text()或者session.read .format( "テキスト").OPTIONS(地図( "" - > "B"))。負荷( "")
。読む:オブジェクトの作成DataFrameReader
方法フォーマット:DataFrameReadeを割り当てられたデータ・ソース・タイプ
オプション方法:割り当てDataFrameReade追加の構成オプション
内部はsession.read.text()メソッドを入力して、あなたはフォーマットが「テキスト」で見ることができます
Loadメソッドに(2)
負荷があることが判明:sparkSession.baseRelationToDataFrameこの方法は、最終的にデータフレームを作成します
(3 )に入るデータソースresolveRelation()メソッドを
この段落は、次のとおりprovidingClassこのクラスは、無着信スキーマ2つのシェマとに分割されているインタフェースが存在する実装するクラスであります
(3)providingClassフォーマットは、着信データ・ソース・タイプであり、ソースの前にあります
地図スパーク源は、すべてのデータを提供します
4. ちょうど実装RelationProviderがメソッドbaserelationに戻る方法は、次のことクラスを作成結論します
DEFのCreateRelation(sqlContext:SQLContext、パラメータ:地図[文字列、文字列]):BaseRelation
我们在实现baserelation里面的逻辑就可以了
5.看看spark读取jdbc类
需要一个类,实现xxxScan这中类,这种类有三种,全局扫描tableScan,PrunedFilteredScan(列裁剪与谓词下推),PrunedScan ,
实现buildscan方法返回row类型rdd,结合baserelation有shcame这个变量 ,就凑成了dataframe
6.jdbcRdd.scanTable方法,得到RDD
7.查看jdbcRDD的compute方法,是通过jdbc查询sql的方式获取数据
RDD的计算是惰性的,一系列转换操作只有在遇到动作操作是才会去计算数据,而分区作为数据计算的基本单位。在计算链中,无论一个RDD有多么复杂,其最终都会调用内部的compute函数来计算一个分区的数据。
override def compute(thePart: Partition, context: TaskContext): Iterator[InternalRow] = { var closed = false var rs: ResultSet = null var stmt: PreparedStatement = null var conn: Connection = null def close() { if (closed) return try { if (null != rs) { rs.close() } } catch { case e: Exception => logWarning("Exception closing resultset", e) } try { if (null != stmt) { stmt.close() } } catch { case e: Exception => logWarning("Exception closing statement", e) } try { if (null != conn) { if (!conn.isClosed && !conn.getAutoCommit) { try { conn.commit() } catch { case NonFatal(e) => logWarning("Exception committing transaction", e) } } conn.close() } logInfo("closed connection") } catch { case e: Exception => logWarning("Exception closing connection", e) } closed = true } context.addTaskCompletionListener{ context => close() } val inputMetrics = context.taskMetrics().inputMetrics val part = thePart.asInstanceOf[JDBCPartition] conn = getConnection() val dialect = JdbcDialects.get(url) import scala.collection.JavaConverters._ dialect.beforeFetch(conn, options.asProperties.asScala.toMap) // H2's JDBC driver does not support the setSchema() method. We pass a // fully-qualified table name in the SELECT statement. I don't know how to // talk about a table in a completely portable way. //坐上每个分区的Filter条件 val myWhereClause = getWhereClause(part) //最終查询sql语句 val sqlText = s"SELECT $columnList FROM ${options.table} $myWhereClause" //jdbc查询 stmt = conn.prepareStatement(sqlText, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY) stmt.setFetchSize(options.fetchSize) rs = stmt.executeQuery() val rowsIterator = JdbcUtils.resultSetToSparkInternalRows(rs, schema, inputMetrics) //返回迭代器 CompletionIterator[InternalRow, Iterator[InternalRow]]( new InterruptibleIterator(context, rowsIterator), close()) }