从 PySpark 查询日期之间的 Vertica

Posted

技术标签:

【中文标题】从 PySpark 查询日期之间的 Vertica【英文标题】:Query Vertica between dates from PySpark 【发布时间】:2019-02-14 20:22:57 【问题描述】:

我在 Python 3.4 上运行 Spark 1.6,从我的 Vertica 数据库中检索数据以处理以下查询,Spark DataFrames 支持使用 JDBC 源的谓词下推,但术语谓词用于严格的 SQL 含义。这意味着它仅涵盖 WHERE 子句。此外,它看起来仅限于逻辑连词(恐怕没有 IN 和 OR)和简单的谓词,它显示了这个错误:java.lang.RuntimeException: Option 'dbtable' not specified

数据库包含大约 1000 亿的海量数据,我无法检索数据 并且 spark1.6 不允许我使用仅查询 dbtable 作为 schema.table,我得到了以下错误:

java.lang.RuntimeException: Option 'dbtable' not specified
sc = SparkContext(conf=conf)
sqlContext = SQLContext(sc)

url = "*******"
properties = "user": "*****", "password": "*******", "driver": "com.vertica.jdbc.Driver" 

df = sqlContext.read.format("JDBC").options(
    url = url,
    query = "SELECT date(time_stamp) AS DATE, (subscriber) AS IMSI, (server_hostname) AS WEBSITE, (bytes_in) AS DOWNLINK, (bytes_out) AS UPLINK,(connections_out) AS CONNECTION FROM traffic.stats WHERE DATE(time_stamp) between '2019-01-25' AND '2019-01-29'",
    **properties
).load()

df.show()

我已经尝试了以下查询,但没有使用限制功能需要很长时间

query = "SELECT date(time_stamp) AS DATE, (subscriber) AS IMSI, (server_hostname) AS WEBSITE, (bytes_in) AS DOWNLINK, (bytes_out) AS UPLINK,(connections_out) AS CONNECTION FROM traffic.stats WHERE date(time_stamp) between '2019-01-27' AND '2019-01-29'"
df = sqlContext.read.format("JDBC").options(
    url = url,
    dbtable="( " + query + " ) as temp",
    **properties
).load()

是否仍然可以像上面那样读取数据或将其作为具有特定查询的数据框读取?

我试图通过设置更多的条件和限制来减少时间,但它在 $\conditions 上被拒绝,即使删除它给我的条件“FROM 中的子查询必须有一个别名”,这是查询:

SELECT min(date(time_stamp)) AS mindate,max(date(time_stamp)) AS maxdate,count (distinct date(time_stamp)) AS noofdays, (subscriber) AS IMSI, (server_hostname) AS WEBSITE, sum(bytes_in) AS DL, sum(bytes_out) AS UL, sum(connections_out) AS conn from traffic.stats where SUBSCRIBER like '41601%' and date(time_stamp) between '2019-01-25' and '2019-01-29'and signature_service_category = 'Web Browsing' and (signature_service_name = 'SSL v3' or signature_service_name = 'HTTP2 over TLS') and server_hostname not like '%.googleapis.%' and server_hostname not like '%.google.%' and server_hostname <> 'doubleclick.net'  and server_hostname <> 'youtube.com'  and server_hostname <> 'googleadservices.com'  and server_hostname <> 'app-measurement.com' and server_hostname <> 'gstatic.com' and server_hostname <> 'googlesyndication.com' and server_hostname <> 'google-analytics.com'  and server_hostname <> 'googleusercontent.com'  and server_hostname <> 'ggpht.com'  and server_hostname <> 'googletagmanager.com' and server_hostname is not null group by subscriber, server_hostname

【问题讨论】:

traffic.stats 表有多少行?查询(使用日期范围过滤器)返回多少行?直接对 Vertica 执行查询需要多长时间? 超过1000亿,执行时间需要一个多小时 【参考方案1】:

如果查询在日期范围之间过滤的时间超过一个小时,您应该考虑编写投影。

CREATE PROJECTION traffic.status_date_range
(
  time_stamp,
  subscriber,
  server_hostname,
  bytes_in,
  bytes_out,
  connections_out
)
AS
  SELECT
    time_stamp,
    subscriber,
    server_hostname,
    bytes_in,
    bytes_out,
    connections_out
  FROM traffic.stats
  ORDER BY time_stamp
SEGMENTED BY HASH(time_stamp) ALL NODES;

像这样创建特定于查询的投影可能会增加大量磁盘空间,但如果性能对您来说真的很重要,那么它可能是值得的。

如果您还没有这样做,我还建议您对表进行分区。根据您在 traffic.stats 表中有多少不同的日期,您可能不想按天进行分区。每个分区至少创建 1 个 ROS 容器(有时更多)。因此,如果您有 1024 个或更多不同的日期,那么 Vertica 甚至不会让您按日期分区,在这种情况下您可以按月分区。如果您使用的是 Vertica 9,那么您可以利用 Hierarchal Partitioning(您可以阅读 here 的相关信息)。

我要提醒的是,在运行 ALTER TABLE 语句以添加分区子句后重组表将需要大量磁盘空间,因为 Vertica 将数据写入新文件。完成后,该表将占用与现在几乎相同的空间量,但在分区时,您的磁盘空间可能会变得非常大。

【讨论】:

太棒了,谢谢,我已经编辑了我的帖子,请你检查最后一阶段,谢谢。 请发布您使用的确切语句,以及包含 $\conditions 错误的完整回溯。谢谢。 我已经编辑了最后一部分的问题,当我尝试运行它时返回 ERROR: Syntax error at or near "\" ,即使我删除了 \$condtion ,它返回“错误:FROM 中的子查询必须有别名” 我仍然对$\conditions 感到困惑。您一直说您收到有关 $\conditions 的错误,但我在您正在运行的 spark 语句或正在执行的 Vertica 查询中没有看到任何类似的内容。请发布您正在使用的引发此错误的确切语句。

以上是关于从 PySpark 查询日期之间的 Vertica的主要内容,如果未能解决你的问题,请参考以下文章

从 impala 更新 vertica 中的巨大记录

在 Vertica 中运行递归查询

在 Hive 或 Pyspark 中查询以获取每个星期日和星期六的日期

.Net 核心支持查询 Vertica

从 vertica 导入 sqoop 失败

无法从 Spark 显示 Vertica 表