web-dev-qa-db-ja.com

Spark SQLクエリからのデータフレームを作成

これは単純なSQLContextの質問であると確信していますが、Spark docsまたはStackoverflowに答えが見つかりません

MySQLのSQLクエリからSpark Dataframeを作成したい

たとえば、次のような複雑なMySQLクエリがあります

SELECT a.X,b.Y,c.Z FROM FOO as a JOIN BAR as b ON ... JOIN ZOT as c ON ... WHERE ...

x、Y、Z列のデータフレームが必要です

テーブル全体をSparkにロードする方法を考え出しました。すべてロードしてから、そこで結合と選択を行うことができました。ただし、それは非常に非効率的です。 SQLクエリによって生成されたテーブルを読み込むだけです。

ここに、現在のコードの近似を示しますが、うまくいきません。 Mysql-connectorには、テーブル全体をロードするために使用できるオプション「dbtable」があります。クエリを指定する方法があることを願っています

  val df = sqlContext.format("jdbc").
    option("url", "jdbc:mysql://localhost:3306/local_content").
    option("driver", "com.mysql.jdbc.Driver").
    option("useUnicode", "true").
    option("continueBatchOnError","true").
    option("useSSL", "false").
    option("user", "root").
    option("password", "").
    sql(
"""
select dl.DialogLineID, dlwim.Sequence, wi.WordRootID from Dialog as d
join DialogLine as dl on dl.DialogID=d.DialogID
join DialogLineWordInstanceMatch as dlwim o n dlwim.DialogLineID=dl.DialogLineID
join WordInstance as wi on wi.WordInstanceID=dlwim.WordInstanceID
join WordRoot as wr on wr.WordRootID=wi.WordRootID
where d.InSite=1 and dl.Active=1
limit 100
"""
    ).load()

ありがとうピーター

13
user1902291

答えは次のとおりです...

ここでこれを見つけました Spark SQLを介したバルクデータ移行

Dbnameパラメータには、エイリアス付きの括弧で囲まれたクエリを指定できます。だから私の場合、これをする必要があります...

val query = """
  (select dl.DialogLineID, dlwim.Sequence, wi.WordRootID from Dialog as d
    join DialogLine as dl on dl.DialogID=d.DialogID
    join DialogLineWordInstanceMatch as dlwim on dlwim.DialogLineID=dl.DialogLineID
    join WordInstance as wi on wi.WordInstanceID=dlwim.WordInstanceID
    join WordRoot as wr on wr.WordRootID=wi.WordRootID
    where d.InSite=1 and dl.Active=1
    limit 100) foo
"""

val df = sqlContext.format("jdbc").
  option("url", "jdbc:mysql://localhost:3306/local_content").
  option("driver", "com.mysql.jdbc.Driver").
  option("useUnicode", "true").
  option("continueBatchOnError","true").
  option("useSSL", "false").
  option("user", "root").
  option("password", "").
  option("dbtable",query).
  load()

予想どおり、各テーブルを独自のデータフレームとしてロードしてSparkに結合することは非常に非効率的でした。

32
user1902291

クエリの出力を新しいデータフレームに保存するには、変数に等しい結果を設定するだけです:

val newDataFrame = spark.sql("SELECT a.X,b.Y,c.Z FROM FOO as a JOIN BAR as b ON ... JOIN ZOT as c ON ... WHERE ...")

newDataFrameは、利用可能なすべてのデータフレーム機能を備えたデータフレームです。

1
Kristian

tableSQLContext に既に登録されている場合、単にsqlメソッドを使用できます。

val resultDF = sqlContext.sql("SELECT a.X,b.Y,c.Z FROM FOO as a JOIN BAR as b ON ... JOIN ZOT as c ON ... WHERE ...")
1

mYSQLでは、次のようなデータの読み込み/読み込みを行います

val conf = new SparkConf().setAppName("SparkMe Application").setMaster("local[2]")
    val sc = new SparkContext(conf)
    sc.setLogLevel("ERROR")
    val sqlContext = new org.Apache.spark.sql.SQLContext(sc)
    val jdbcDF = sqlContext.read.format("jdbc").options(
      Map("url" -> "jdbc:mysql://<Host>:3306/corbonJDBC?user=user&password=password",
        "dbtable" -> "TABLE_NAME")).load()

以下のようにデータをテーブルに書き込みます

import Java.util.Properties
    val prop = new Properties()
    prop.put("user", "<>")
    prop.put("password", "simple$123")
    val dfWriter = jdbcDF.write.mode("append")
    dfWriter.jdbc("jdbc:mysql://<Host>:3306/corbonJDBC?user=user&password=password", "tableName", prop)

クエリからデータフレームを作成するには、次のようにします

val finalModelDataDF = {
      val query = "select * from table_name"
      sqlContext.sql(query)
    };

    finalModelDataDF.show()
0

TL; DR:データベースにビューを作成するだけです。

詳細: postgresデータベースにテーブルt_cityがあり、ビューを作成します:

create view v_city_3500 as
    select asciiname, country, population, elevation
    from t_city
    where elevation>3500
    and population>100000

select * from v_city_3500;

 asciiname | country | population | elevation
-----------+---------+------------+-----------
 Potosi    | BO      |     141251 |      3967
 Oruro     | BO      |     208684 |      3936
 La Paz    | BO      |     812799 |      3782
 Lhasa     | CN      |     118721 |      3651
 Puno      | PE      |     116552 |      3825
 Juliaca   | PE      |     245675 |      3834

スパークシェルで:

val sx= new org.Apache.spark.sql.SQLContext(sc)

var props=new Java.util.Properties()
props.setProperty("driver", "org.postgresql.Driver" )
val url="jdbc:postgresql://buya/dmn?user=dmn&password=dmn"

val city_df=sx.read.jdbc(url=url,table="t_city",props)
val city_3500_df=sx.read.jdbc(url=url,table="v_city_3500",props)

結果:

city_df.count()
Long = 145725

city_3500_df.count()
Long = 6
0
WillemM