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
,但发出错误。
答案 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
创建Dataframee.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')]