ETL介绍
通过工具或程序,将零散的数据,统一收集到一个位置进行“集中存储”以便进行“集中分析”。
E:抽取 T:转换 L:加载
ETL与ELT的区别
ETL:先转换再加载,适用于数据业务比较单一的场景,直接处理加载后得到结果
ELT:先加载再转换,适用于数据业务比较复杂的场景,加载后根据不同的业务需求进行处理再应用
传统数据平台的ETL:传统数据业务比较单一,主要实现数据清洗的功能,将非法数据进行过滤处理等
大数据系统中的ETL:大数据业务逻辑比较复杂,所有与数仓相关的计算处理过程统称为ETL
1 常见的数仓ETL工具
传统的ETL工具
特点:所有功能集于一身
代表产品:
Datastage:IBM公司的商业软件,最专业的ETL工具,但同时价格不菲,适合大规模的ETL应用
Informatica:同为商业的专业ETL工具,类似于Datastage,也适合大规模的ETL应用
Kettle:业界最有名的开源ETL工具,用纯java编写的ETL工具,只需要JVM环境即可部署,可跨平台,扩展性好
大数据平台的ETL工具
- 特点:不同的功能由不同的工具来实现
- 工具
- 抽取/采集:Sqoop、Flume、Logstash、Beats、Canal
- 转换/处理:HiveSQL、SparkSQL、Impala、Presto、Kylin
- 调度:Oozie、AirFlow、DS、Azkaban
2 数据格式介绍
csv:由逗号、制表符
json:
xml:标签对,可以与json格式进行转换
结构化、非结构化、半结构化数据
结构化:有固定的schema
id,age,sex
101,10,男
102,20,女
非结构化:没有固定的schema
复杂的json数据
复杂的xml
半结构化数据:一般用算法来处理
图片、视频、音频
3 日志信息
Python logging模块是Python标准库中用于记录日志信息的模块,可以方便地记录应用程序中的事件和错误信息。使用logging模块可以优化代码的调试和维护过程,它可以将日志输出到控制台,文件或其他地方。
设置日志级别
日志级别有以下几种:
DEBUG:详细的信息,通常用于调试;
INFO:确认一切按预期运行;
WARNING:表示有些意外或不习惯的事情发生,或表明一些问题或不必要的情况的警告,但软件仍可继续运行;
ERROR:比警告更严重,但软件仍可继续运行;
CRITICAL:严重错误,表示软件已不能继续运行。
如果遇到错误代码:AttributeError: module 'logging' has no attribute 'getLogger'
,可能是由于模块重名,把logging改为其他名字就好了
import logging
if __name__=='__main__':
# 1、创建logger对象 logging
logger=logging.getLogger()
# 2、创建handler对象 logging
handler=logging.FileHandler(r"F:\Study\code\ETL\pyetlcode\ETLPro\logs\fileLog.log",encoding="utf-8")
# 3、设置日志格式 logging
format=logging.Formatter("%(asctime)s-[%(levelname)s]-%(filename)s[%(lineno)d:%(message)s")
# 4、将日志格式添加到handler里面
handler.setFormatter(format)
# 5、将handler对象添加到logger里面
logger.addHandler(handler)
# 6、设置日志级别
logger.setLevel(20)
# 7、输出日志
logger.info("普通日志")
logger.warning("告警日志")
logger.error("报错啦")
解决日志存储问题
日志保存在logs文件夹下:可以将logs文件夹的路径保存在配置文件
日志不断的产生,不可能使用同一个文件保存所有的日志数据:
用随机数+文件大小;用时间(天或小时)改变文件名称;
获取当前时间,转换为天或小时,使用time模块。
获取当前时间,指定格式生成文件名
# 日期日志配置
import time
# 获取当前时间
currentTime=time.time()
print(currentTime)
# 人性化显示日期
personTime=time.localtime(currentTime)
print(personTime)
# 转成格式化时间
resultTime=time.strftime('%Y_%m_%d_%H',personTime)
print(resultTime)
# 日志文件名
log_name=f"etl_{resultTime}.log"
print(log_name)
# 日志存储位置
log_root_path=r"F:\Study\code\ETL\pyetlcode\ETLPro\logs"
递归函数
深度不固定的时候可以用递归函数
注意:1、深度不固定的时候用递归函数; 2、规则必须是准确的
def myrecur(n):
"""
递归函数
深度不固定的时候用递归函数
:param n:
:return:
"""
if n==1: # 收敛值,最里层的值一定是死的
return 2
else:
r=2*myrecur(n-1)+1 # 2.规则必须是准确的
return r
if __name__ == '__main__':
print(myrecur(3)) # 结果是11
工具类实现:mysql工具类
方便我们对数据库的使用, 我们直接封装一个mysql工具类, 方便我们的mysql使用
实践过程中发现的错误:
raise errorclass(errno, errval) pymysql.err.OperationalError: (1045, "Access denied for user 'root'@'localhost' (using password: NO)")
连接到 MySQL 数据库时使用了错误的用户名或密码。检查下MySQL 用户名和密码是否正确,或者是否有权限连接到数据库,检查完后发现密码写错了,改好就可以连接上了
pymysql.err.IntegrityError: (1062, "Duplicate entry 'person' for key 'file_name'")
Mysql 报错Duplicate entry ‘值’ for key ‘字段名’ 解决:错误原因是表中唯一值重复
查询数据库发现file_name列添加了唯一索引,而数据表中已存在同样的数据
RuntimeError: 'cryptography' package is required for sha256_password or caching_sha2_password auth methods
数据库没成功连接,重启下数据库
pymysql.err.InterfaceError: (0, '')
:数据库连接的实例化对象没有关闭