繁体   English   中英

有限制地将表格加载到PySpark Dataframe中

[英]Loading a table into PySpark Dataframe with limits

在PySpark中是否有可能在从数据库中读取数据时将一定数量的数据加载到数据框中? 一定数量,我的意思是说从数据库读取sqlContext时是否可以给它一个限制,从而sqlContext读取整个表(因为遍历750K行非常昂贵)。

这是我当前用于过滤所需数据的代码。 除了PySpark外,我还使用了Python3.7和Cassandra DB:

def connect_cassandra():
    spark = SparkSession.builder \
      .appName('SparkCassandraApp') \
      .config('spark.cassandra.connection.host', 'localhost') \
      .config("spark.driver.memory","15g") \
      .config("spark.executor.memory","15g") \
      .config("spark.driver.cores","4") \
      .config("spark.num.executors","6") \
      .config("spark.executor.cores","4") \
      .config('spark.cassandra.connection.port', '9042') \
      .config('spark.cassandra.output.consistency.level','ONE') \
      .master('local[*]') \
      .getOrCreate()

    sqlContext = SQLContext(spark)
    return sqlContext

def total_bandwidth(start_date, end_date):
    sqlContext = connect_cassandra()

    try:
        df = sqlContext \
          .read \
          .format("org.apache.spark.sql.cassandra") \
          .options(table="user_info", keyspace="acrs") \
          .load()
    except Exception as e:
        print(e)

    rows = df.where(df["created"] > str(start_date)) \
            .where(df["created"] < str(end_date)) \
            .groupBy(['src_ip', 'dst_ip']) \
            .agg(_sum('data').alias('total')) \
            .collect()

    data_dict = []
    for row in rows:
        src_ip = row['src_ip']
        dst_ip = row['dst_ip']
        data = row['total']
        data = {'src_ip' : src_ip, 'dst_ip' : dst_ip, 'data' : data}
        data_dict.append(data)

    print(data_dict)

如你们所见,我正在尝试使用start_dateend_date过滤数据。 但这会花费太多时间,导致操作缓慢。 我想知道在将表加载到数据框中时是否有任何DataFrameReader选项可用,这样所花费的时间减少了(呈指数形式首选:p)。

我阅读了Data-Frame-Reader文档并找到了option(String key, String value)但是这些选项未记录在文档中,因此无法找出Cassandra数据库有哪些选项以及如何使用它们。

您的主要问题是您正在使用append方法。 由于您的数据框中有很多行,因此效率很低。 我宁愿使用专用的pyspark方法来获得所需的结果。

我在本地计算机上创建了一些临时数据帧(假定您已经创建了SparkSession),其中包含一百万行

>>> import pandas as pd

>>> n = 1000000
>>> df = spark.createDataFrame(
        pd.DataFrame({
            'src_ip': n * ['192.160.1.0'],
            'dst_ip': n * ['192.168.1.1'],
            'total': n * [1]
        })
    )
>>> df.count()
1000000

让我们仅从表中选择所需的列。

>>> import pyspark.sql.functions as F
>>> df.select('src_ip', 'dst_ip', F.col('total').alias('data')).show(5)
+-----------+-----------+----+
|     src_ip|     dst_ip|data|
+-----------+-----------+----+
|192.160.1.0|192.168.1.1|   1|
|192.160.1.0|192.168.1.1|   1|
|192.160.1.0|192.168.1.1|   1|
|192.160.1.0|192.168.1.1|   1|
|192.160.1.0|192.168.1.1|   1|
+-----------+-----------+----+
only showing top 5 rows

最后,让我们创建所需的数据字典列表。 收集所有数据的最简单方法是使用列表推导。 一旦选择了要合并为字典的列,就可以在每个DataFrame行上使用toDict()方法。

鸡蛋里挑骨头:

  • 如果要收集所有值,请在DataFrame上使用collect()方法。
  • 如果您不知道DataFrame的确切大小,则可以使用take(n)方法,该方法将从DataFrame中返回n元素。
>>> dict_list = [i.asDict() for i in df.select('src_ip', 'dst_ip', F.col('total').alias('data')).take(5)]
>>> dict_list
[{'data': 1, 'dst_ip': '192.168.1.1', 'src_ip': '192.160.1.0'},
 {'data': 1, 'dst_ip': '192.168.1.1', 'src_ip': '192.160.1.0'},
 {'data': 1, 'dst_ip': '192.168.1.1', 'src_ip': '192.160.1.0'},
 {'data': 1, 'dst_ip': '192.168.1.1', 'src_ip': '192.160.1.0'},
 {'data': 1, 'dst_ip': '192.168.1.1', 'src_ip': '192.160.1.0'}]

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM