Spark程序需要很长时间才能完成执行

时间:2016-11-09 07:53:42

标签: apache-spark pyspark

Spark应该以闪电般的速度完成数据处理。但我想我没有在我的程序中使用正确的功能来使Spark以这种方式工作。

这就是我的程序的样子:

from pyspark import SparkContext
from pyspark import SQLContext
from pyspark.sql.types import *
from pyspark.sql import Row
from pyparsing import re
import time

start_time = time.time()
sc = SparkContext("local","test")
sqlContext = SQLContext(sc)

def func1(lines):
    for line in lines:
        qtype = re.search("qtype=(\S+)",line)
        try:
            url = re.search(" url=(\S+)",line)
            url=url.group(1)
        except:
            url="null"

        time = re.search("(^\S+)",line)
        .... #extracting field names
        row = Row(time = time.group(1),ttms = ttms.group(1),chi = chi.group(1),pssc = pssc.group(1),cqhm = cqhm.group(1),rtype = rtype.group(1),rdetails = rdetails.group(1),rurl = rurl.group(1),qtype = qtype.group(1),phn = phn.group(1),fqdn = fqdn,url = url)

    return row

file = sc.textFile("C:\\Logs\\filename.log").cache()
result = file.map(lambda x: x.split("\n"))
lines = result.map(func1).collect()
df = sqlContext.createDataFrame(lines)
df.registerTempTable("df")
df.show()

for line in df :
    query1 = sqlContext.sql("SELECT qtype,rtype,COUNT(qtype,rtype) from df GROUP BY qtype,rtype").collect()
    query2 = sqlContext.sql("SELECT qtype, COUNT(qtype) from df GROUP BY qtype").collect()
    query3 = sqlContext.sql("SELECT rtype, COUNT(rtype) from df GROUP BY rtype").collect()
    query4 = sqlContext.sql("SELECT rtype, COUNT(rtype) from df WHERE qtype = \"HTTP\" GROUP BY rtype").collect()

df1 = sqlContext.createDataFrame(query1)
df2 = sqlContext.createDataFrame(query2)
df3 = sqlContext.createDataFrame(query3)
df4 = sqlContext.createDataFrame(query4)
df1.toPandas().to_csv("C:\\Sample logs\\sqlcsv1.csv")
df2.toPandas().to_csv("C:\\Sample logs\\sqlcsv2.csv")
df3.toPandas().to_csv("C:\\Sample logs\\sqlcsv3.csv")
df4.toPandas().to_csv("C:\\Sample logs\\sqlcsv4.csv")
print(time.time() - start_time)

这个程序需要大约200秒才能执行,这是一个很长的时间。我无法弄清楚原因。 (我的日志文件包含大约34k日志行)。我尝试使用spark filter来表示正则表达式,但我得到的错误是rdd is not iterable。所以我需要知道以什么方式优化我的程序以使其运行得更快。 另外,我收到stage x contains task of very large size的警告。尝试播放lines,但发出错误。

1 个答案:

答案 0 :(得分:5)

为什么这个spark代码会比纯python代码运行得慢一些原因:

1)使用一台机器

sc = SparkContext("local","test")
在群集上运行时,python-spark可能比纯python执行得更好。 在“本地”模式下,spark对纯python没有任何优势。

2)不使用时使用“缓存”

file = sc.textFile("C:\\Logs\\filename.log").cache()
只有在多次调用同一个对象时才应使用

.cache()。 “file”只被调用一次 - 即不需要缓存

3)使用“collect()”

lines = result.map(func1).collect()

for line in df :
    query1 = sqlContext.sql("SELECT qtype,rtype,COUNT(qtype,rtype) from df GROUP BY qtype,rtype").collect()
    query2 = sqlContext.sql("SELECT qtype, COUNT(qtype) from df GROUP BY qtype").collect()
    query3 = sqlContext.sql("SELECT rtype, COUNT(rtype) from df GROUP BY rtype").collect()
    query4 = sqlContext.sql("SELECT rtype, COUNT(rtype) from df WHERE qtype = \"HTTP\" GROUP BY rtype").collect()

一般规则 - 避免使用“collect()”,除非确实需要它。

4)使用“toPandas()”

df1.toPandas().to_csv("C:\\Sample logs\\sqlcsv1.csv")
df2.toPandas().to_csv("C:\\Sample logs\\sqlcsv2.csv")
df3.toPandas().to_csv("C:\\Sample logs\\sqlcsv3.csv")
df4.toPandas().to_csv("C:\\Sample logs\\sqlcsv4.csv")

“toPandas()”实现从执行“collect()”开始(参见#3)

自spark 2.0起,您可以直接将数据帧写入CSV:

http://spark.apache.org/docs/2.0.1/api/python/pyspark.sql.html#pyspark.sql.DataFrameWriter

>>> df.write.csv(os.path.join(tempfile.mkdtemp(), 'data'))

5)我不确定我是否理解以下代码:

for line in df :
    query1 = sqlContext.sql("SELECT qtype,rtype,COUNT(qtype,rtype) from df GROUP BY qtype,rtype").collect()
    query2 = sqlContext.sql("SELECT qtype, COUNT(qtype) from df GROUP BY qtype").collect()
    query3 = sqlContext.sql("SELECT rtype, COUNT(rtype) from df GROUP BY rtype").collect()
    query4 = sqlContext.sql("SELECT rtype, COUNT(rtype) from df WHERE qtype = \"HTTP\" GROUP BY rtype").collect()

你在“for line in df:”中尝试实现了什么?

如果数据帧包含100,000行,您是否计划执行此“for-loop”100,000次?

似乎变量query1,query2,query3,query4将仅保存for循环的最后一次执行的结果(因为每次从“df”读取新的“行”时它们的值似乎都会被覆盖) - 是出于目的吗?

6)您可以直接从RDD

创建Dataframe

e.g。使用

sqlContext.createDataFrame

http://spark.apache.org/docs/2.0.1/api/python/pyspark.sql.html

createDataFrame(** data,schema = None,samplingRatio = None,verifySchema = True) **从RDD创建DataFrame,列表或pandas.DataFrame。

RDD.toDF()

http://spark.apache.org/docs/2.0.1/api/python/pyspark.sql.html

toDF(* COLS)

返回一个新类:具有新指定列名的DataFrame 参数:cols - 新列名列表(字符串)

>>> df.toDF('f1', 'f2').collect()
[Row(f1=2, f2=u'Alice'), Row(f1=5, f2=u'Bob')]