如何从像key1 =“ value1” key2 =“ value2”

时间:2019-05-08 22:28:19

标签: apache-spark dataframe hive pyspark apache-spark-sql

概述

我正在使用具有几列的syslog文本文件,但最后一列只是一串键值对。

最后一列的格式为 key1 =“ value1” key2 =“ value2” key3 =“ value3带有空格”

这些键可能只有1个。

我的目标是将数据框拆分为两个新的数据框。一个是在所有消息中都保持一致的列,并是固定数量的列和另一个是键值对的数据帧,其中每个键/值对都在其自己的行中(因为它们的大小是动态的)。 / p>

然后我可以对原始数据帧运行sql select语句,并加入新的数据帧以隔离我想要的选择键,并与其他数据集混搭。

我有一套可以正常工作的测试代码,但是在其中的某些部分苦苦挣扎。

  1. 这是以有效的方式完成的吗?该文件将位于Amazon Web Services中,每天处理约4GB的这些文本文件(压缩后的文件较小,但未压缩时的文件大小则较大)。
  2. 我利用monotonically_increasing_id()函数。那是个问题吗?我看过一些较旧的页面,讨论有关它的问题。

消息行示例

# Apr 1 23:59:59 server1.mycompany.com datetime="2019-04-02T05:50:11Z" timestamp="1554184211000" script="ServerDataCollector" processTimeCount="35" Name="'Test Location'"
# Apr 1 23:59:59 server2.mycompany.com datetime="2019-04-02T05:50:11Z" timestamp="1554184211000" script="ClientDataCollector" Name="'Test Location2' upTime="23513", faultsLast24Hours="0"

这将在AWS中使用,粘合搜寻器将自动以以下格式注册数据:

  • 时间戳:字符串(例如4月1日23:59:59)
  • 主机:字符串(例如hub-ca-cfg-pro-08-00v.int.pason.com)
  • kernel_logs:字符串(例如datetime =“ 2019-04-02T05:50:11Z” timestamp =“ 1554184211000” script =“ myServer” ...)

因此,在没有自定义搜寻器或表体验的情况下,我的数据框看起来像上面的三列。

对于此示例,我将得到以下数据帧,这是一些用于设置示例的代码:

#   rawDataFrame: The original data set
#        date
#        host
#        kernel_logs
#   headersDataFrame: The first two columns with a unique identifier added
#        message_id: unique key
#        date:
#        host:
#   detailsDataFrame: Table containing a row for every key/value pair
#        message_id
#        key
#        value
#
#  The concept being I can do a query like:
#  SELECT
#   *
#  FROM headersDataFrame
#  INNER JOIN detailsDataFrame USING (message_id)
#  WHERE detailsDataFrame.key="something"
#     AND headersDataFrame.date=today()
#
#

from pyspark import SparkContext, SQLContext
from pyspark.sql import *
from pyspark.sql.functions import monotonically_increasing_id, split

#sc = SparkContext()
#spark = SQLContext(sc)

Message = Row("date", "host", "kernel_logs")

message1 = Message( \
        'Apr 1 23:59:59', \
        'server1.mycompany.com', \
        'datetime="2019-04-02T05:50:11Z" timestamp="1554184211000" script="ServerDataCollector" processTimeCount="35" Name="\'Test Location\'"' \
    )

message2 = Message( \
        'Apr 1 23:59:59', \
        'server2.mycompany.com', \
        'datetime="2019-04-02T05:50:11Z" timestamp="1554184211000" script="ClientDataCollector" Name="\'Test Location2\'"" upTime="23513" faultsLast24Hours="0"' \
    )

messageSequence = [message1, message2]

rawDataFrame = spark.createDataFrame(messageSequence)

rawDataFrame.show(truncate=False)
  

启动Spark应用程序ID YARN应用程序ID种类状态Spark   UI驱动程序日志当前会话?   7 application_1557428720231_0008 pyspark空闲链接链接✔SparkSession   可作为“火花”使用。   + -------------- + --------------------- + ------------ -------------------------------------------------- -------------------------------------------------- ------------------------------------ + |日期|主机|内核日志
  |   + -------------- + --------------------- + ------------ -------------------------------------------------- -------------------------------------------------- ------------------------------------ + | 4月1日23:59:59 | server1.mycompany。 com | datetime =“ 2019-04-02T05:50:11Z”   timestamp =“ 1554184211000” script =“ ServerDataCollector”   processTimeCount =“ 35” Name =“'测试位置'” | | 4月1日   23:59:59 | server2.mycompany.com | datetime =“ 2019-04-02T05:50:11Z”   timestamp =“ 1554184211000” script =“ ClientDataCollector” Name =“'Test   Location2'“” upTime =“ 23513” faultsLast24Hours =“ 0” |   + -------------- + --------------------- + ------------ -------------------------------------------------- -------------------------------------------------- ------------------------------------ +

当前代码

需要添加唯一键才能在两个表之间进行查找。我确实看到了一篇有关monotonically_increasing_id()函数问题的文章,但尚未处理我的较大数据集,以查看它是否会创建重复项(在过去的其他疑难解答文章中列出)。

rawDataFrameWithPrimaryKey = rawDataFrame.withColumn('message_id', monotonically_increasing_id())

rawDataFrameWithPrimaryKey.show()
  

+ -------------- + -------------------- + ---------- ---------- + ---------- + |日期|主持人| kernel_logs | message_id |   + -------------- + -------------------- + ------------- ------- + ---------- + | 4月1日23:59:59 | server1.mycompany ... | datetime =“ 2019-04 ... | 0 |   | 4月1日23:59:59 | server2.mycompany ... | datetime =“ 2019-04 ... | 8589934592 |   + -------------- + -------------------- + ------------- ------- + ---------- +

现在拆分为单独的数据帧。

headersDataFrame = rawDataFrameWithPrimaryKey.drop('kernel_logs')
detailsDataFrame = rawDataFrameWithPrimaryKey.drop('date') \
                                             .drop('host')

headersDataFrame.show()
detailsDataFrame.show()

    # Split the key/value pair column into an array
detailsDataFrame = detailsDataFrame.withColumn("kernel_logs", split("kernel_logs", "\" "))

detailsDataFrame.show()
  

+ -------------- + -------------------- + ---------- + |日期|主机| message_id |   + -------------- + -------------------- + ---------- + |四月1 23:59:59 | server1.mycompany ... | 0 | | 4月1日   23:59:59 | server2.mycompany ... | 8589934592 |   + -------------- + -------------------- + ---------- +      

+ -------------------- + ---------- + | kernel_logs | message_id |   + -------------------- + ---------- + | [datetime =“ 2019-0 ... | 0 | || [datetime =“ 2019-0 ... | 8589934592 |   + -------------------- + ---------- +

现在,我们需要为每个键/值对创建多个行。

from pyspark.sql.types import ArrayType, StructType, StructField, StringType
from pyspark.sql.functions import col, udf, explode

zip_ = udf(
  lambda x: list(zip(x)),
  ArrayType(StructType([
      # Adjust types to reflect data types
      StructField("first", StringType())
  ]))
)

explodedDetailsDataFrame = (detailsDataFrame
    .withColumn("tmp", zip_("kernel_logs"))
    # UDF output cannot be directly passed to explode
    .withColumn("tmp", explode("tmp"))
    .select("message_id", col("tmp.first").alias("keyvalue"))
)

让我们拆分键值列

split_col = split(explodedDetailsDataFrame["keyvalue"], '="')

detailsDataFrame = explodedDetailsDataFrame \
                                .withColumn("key", split_col.getItem(0)) \
                                .withColumn("value", split_col.getItem(1)) \
                                .drop("keyvalue")

detailsDataFrame.show(truncate=False)
  

+ ---------- + ----------------- + ----------------- --- + | message_id | key | value |   + ---------- + ----------------- + -------------------- + | 0 |日期时间| 2019-04-02T05:50:11Z | | 0 |时间戳记
  | 1554184211000 | | 0 |脚本
  | ServerDataCollector | | 0 | processTimeCount | 35
  | | 0 |名称|“测试位置”” |   | 8589934592 |日期时间| 2019-04-02T05:50:11Z |   | 8589934592 |时间戳记| 1554184211000 | | 8589934592 |脚本   | ClientDataCollector | | 8589934592 |名称|“测试位置2””   | | 8589934592 |正常运行时间| 23513 |   | 8589934592 | faultsLast24Hours | 0“ |   + ---------- + ----------------- + -------------------- +

0 个答案:

没有答案