如何使用Python(没有PySpark)将pandas数据帧插入现有的配置单元外部表?

如何使用Python(没有PySpark)将pandas数据帧插入现有的配置单元外部表?,python,pandas,dataframe,hive,Python,Pandas,Dataframe,Hive,我正在创建一个到配置单元的连接字符串,并在该连接上的配置单元表上运行一些SELECT查询 在对检索到的数据执行一些转换之后,我正在创建一个数据框df_student_credits,如下所示 NAME_STUDENT_INITIAL CREDITS_INITIAL NAME_STUDENT_FINAL CREDITS_FINAL LOAD_DATE John 23 John

我正在创建一个到配置单元的连接字符串,并在该连接上的配置单元表上运行一些SELECT查询

在对检索到的数据执行一些转换之后,我正在创建一个数据框
df_student_credits
,如下所示

NAME_STUDENT_INITIAL    CREDITS_INITIAL     NAME_STUDENT_FINAL  CREDITS_FINAL   LOAD_DATE
John                    23                  John                25              21/03/2017
Alan                    19                  Alan                19              17/06/2018
Will                    24                  Will                26              02/08/2019
Lily                    25                  Lily                25              22/01/2019
现在,我想将此数据框插入到使用以下命令创建的配置单元外部表中:

CREATE EXTERNAL TABLE IF NOT EXISTS school_db.student_credits
(
NAME_STUDENT_INITIAL STRING,
CREDITS_INITIAL STRING,
NAME_STUDENT_FINAL STRING,
CREDITS_FINAL STRING,
LOAD_DATE STRING
)
LOCATION '/user/gradebook/student_credits/';
我希望每次运行此脚本并生成dataframe时,插入都被追加到表中,而不是覆盖现有的表数据

我看到的几乎每一篇文章都展示了使用PySpark实现这一点的方法。但是我不能使用PySpark,我必须使用与触发SELECT查询相同的python脚本来实现这一点


我对Hive非常陌生,是Python的新手。有人能帮我解决这个问题吗?

在我得到确切答案之前,这里有一些建议

没有分区,HDFS什么都不是。在您的情况下,您还没有定义任何分区。将其作为默认设置从来都不是一个好主意。这是您的数据,您必须知道如何对其进行分区。因此,添加一个适当的分区by子句

假设LOAD_DATE是要设置分区的列。将数据帧转储为拼花格式。 对于HDFS数据,我保持与拼花地板路径相同的路径。 现在按如下所示:

CREATE EXTERNAL TABLE IF NOT EXISTS school_db.student_credits
(
NAME_STUDENT_INITIAL STRING,
CREDITS_INITIAL STRING,
NAME_STUDENT_FINAL STRING,
CREDITS_FINAL STRING
)
partitioned by (LOAD_DATE STRING
ROW FORMAT SERDE 'parquet.hive.serde.ParquetHiveSerDe'
  STORED AS
    INPUTFORMAT "parquet.hive.DeprecatedParquetInputFormat"
    OUTPUTFORMAT "parquet.hive.DeprecatedParquetOutputFormat"
location '/user/gradebook/student_credits';

set hive.msck.path.validation=ignore;
msck repair table school_db.student_credits;
这里的
修复
命令是您每天需要启动的命令。这将刷新数据和新分区

关于如何将数据框转储到拼花地板文件中,请使用以下命令

df_student_credits.write.mode("append").partitionBy("LOAD_DATE").parquet("user/gradebook/student_credits")
首先创建拼花地板文件,然后创建外部桌子。
让我知道这是否解决了您的问题

您似乎正在尝试从配置单元表读入pandas数据帧,并进行一些转换并将其保存回某个配置单元外部表。请参考以下代码作为示例。在这里,我将Hive表中的数据读取到pandas数据框中,并在其中添加了一些日期列。后来,我使用子流程模块来执行shell,它将数据加载到配置单元表中,配置单元表在某个日期列上进行了分区

from pyhive import hive
import pandas as pd
import sqlalchemy
from sqlalchemy.engine import create_engine
import datetime
from subprocess import PIPE, Popen
import subprocess
import sys

conn = hive.Connection(host="yourhost.com", port=10000, username="vikct001")
cursor = conn.cursor()

query="select user_id,country from test_dev_db.test_data"

start_time= datetime.datetime.now()

output_file='/home/vikct001/user/vikrant/python/test_data.csv'

data=pd.read_sql(query,conn)
data['current_date'] = pd.datetime.today().strftime("%Y-%m-%d")
print(data)

data.to_csv(output_file, sep='|', encoding='utf-8',index=None)

hivequery=""" hive --hivevar loaded_date=$(date +"%Y-%m-%d") hive -e 'LOAD DATA LOCAL INPATH "/home/vikct001/user/vikrant/python/test_data.csv" INTO TABLE test_dev_db.test_data_external PARTITION (loaded_date="${hivevar:loaded_date}")';"""

def save_to_hdfs(output_file):
        print("I am here")
        p=subprocess.Popen(hivequery,shell=True,stderr=subprocess.PIPE)
        stdout,stderr = p.communicate()
        if p.returncode != 0:
            print stderr
            sys.exit(1)


save_to_hdfs(output_file)
end_time=datetime.datetime.now()

print 'processing ends', (start_time-end_time).seconds/60.0,' minutes'
表格说明:

hive (test_dev_db)> desc test_dev_db.test_data_external;
OK
id                      int
country                 string
input_date              date
loaded_date             string

# Partition Information
# col_name              data_type               comment

loaded_date             string
您可以看到数据已经加载并创建了一个具有当前日期的分区

hive (test_dev_db)> show partitions test_dev_db.test_data_external;
OK
loaded_date=2019-08-21


hive (test_dev_db)> select * from test_dev_db.test_data_external;
OK
1       India   2019-08-21      2019-08-21
2       Ukraine 2019-08-21      2019-08-21
1       India   2019-08-21      2019-08-21
2       Ukraine 2019-08-21      2019-08-21
1       India   2019-08-21      2019-08-21
2       Ukraine 2019-08-21      2019-08-21
1       India   2019-08-21      2019-08-21

感谢您对分区和代码更改的建议。我会记住这一点。但是,我如何将数据框(例如
df_student_credits
)实际插入到这个配置单元表中呢?df_student_credits.write.mode(“append”).partitionBy(“LOAD_DATE”).parquet(“用户/成绩册/学生信用”)它说:
'DataFrame'对象没有“write”属性。
关于如何解决这个问题有什么想法吗?可能是你可以用它来写入拼花格式。结果我需要用
orc
格式而不是
parquet来写入数据。
我有没有办法将我的数据框直接存储为一个
orc
文件,存储在我在my Hive表创建中使用了,但没有使用PySpark?请在下面找到我的答案。确保为pandas dataframe选择的分隔符必须与create hive external table语句结尾的字段相匹配。Thanks@vikrantrana我无法完全使用您的答案,因为它需要我将数据集保存到csv中。我刚刚更新了你的答案,因为它确实给了我一些新的想法,我正在我的代码中尝试。非常感谢您的回复。如果我最终使用类似的逻辑来解决我的问题,我肯定会回来选择你的作为正确答案。哦,听起来不错。我以前不知道。我也会研究这个选择。非常感谢你提到这件事。