通过查询mysql spark rdd fliter

时间:2017-03-10 09:09:26

标签: mysql filter spark-streaming

我使用spark stream来传输来自Kafka的数据,我希望通过MySql中的数据来过滤数据。

例如,我从kafka获取数据,如:

{"id":1, "data":"abcdefg"}

并且MySql中有数据如下:

id  | state  
1   | "success"

我需要查询MySql以获取term id的状态。 我可以在filter的函数中定义一个到MySql的连接,它可以工作。像这样的代码:

def isSuccess(x):
    id = x["id"]
    sql = """
        SELECT * 
        FROM Test
        WHERE id = "{0}"
        """.format(id)
    conn = mysql_connection(......)
    result = rdbi.query_one(sql)
    if result == None:
        return False
    else:
        return True
successRDD = rdd.filter(isSuccess)

但是它将为RDD的每一行定义连接,并且会浪费大量的计算资源。

过滤器怎么做?

1 个答案:

答案 0 :(得分:1)

我建议您使用Apache Spark中的mapPartition来防止为每个RDD初始化MySQL连接。

这是我创建的MySQL表:

create table test2(id varchar(10), state varchar(10));

使用以下值:

+------+---------+
| id   | state   |
+------+---------+
| 1    | success |
| 2    | stopped |
+------+---------+

使用以下PySpark代码作为参考:

import MySQLdb

data1=[["1", "afdasds"],["2","dfsdfada"],["3","dsfdsf"]] #sampe data, in your case streaming data
rdd = sc.parallelize(data1)

def func1(data1):
    con = MySQLdb.connect(host="127.0.0.1", user="root", passwd="yourpassword", db="yourdb")
    c=con.cursor()
    c.execute("select * from test2;")
    data=c.fetchall()
    dict={}
    for x in data:
        dict[x[0]]=x[1]
    list1=[]
    for x in data1:
        if x[0] in dict:
            list1.append([x[0], x[1], dict[x[0]]])
        else:
            list1.append([x[0], x[1], "none"]) # i assign none if id in table and one received from streaming dont match
    return iter(list1)

print rdd.mapPartitions(func1).filter(lambda x: "none" not in x[2]).collect()

我得到的输出是:

[['1', 'afdasds', 'success'], ['2', 'dfsdfada', 'stopped']]