我正在开发一个项目,该项目有多个远程设备将数据上传到单个MySQL数据库。 (其中一些设备使用带有数据上限的单元调制解调器)
每台设备上传电源使用数据,包含126列浮点数,精度为每2秒4(xx.1234)。
此外,平均每天上传一次208列平均值约2200次。每隔1,5和15分钟。我可能只是从2秒的数据中计算出这些数据,但是在python中对原始数据进行计算要简单得多,而且cpu密集度更低,这只是为了测试这个想法。
我见过的每日最高数据量是130 MiB
单行的csv版本。
# id, dtime, hz, min_v1, avg_v1, max_v1, min_v2, avg_v2, max_v2, min_v3, avg_v3, max_v3, min_i1, avg_i1, max_i1, min_i2, avg_i2, max_i2, min_i3, avg_i3, max_i3, i_n, l1_kw_pa, l2_kw_pb, l3_kw_pc, avg_kw_t, l1_kvar_qa, l2_kvar_qb, l3_kvar_qc, avg_kvar_t, l1_kva_sa, l2_kva_sb, l3_kva_sc, avg_kva_t, l1_pf_pfa, l2_pf_pfb, l3_pf_pfc, avg_pf_t, power_dmd, kvar_dmd, kva_dmd, kwh_imp, kvarh_imp, kwh_t, kvarh_t, kvah_t, v1_thd, v2_thd, v3_thd, i1_thd, i2_thd, i3_thd, p_seq_real_v, p_seq_comp_v, n_seq_real_v, n_seq_comp_v, z_seq_real_v, z_seq_comp_v, p_seq_real_i, p_seq_comp_i, n_seq_real_i, n_seq_comp_i, z_seq_real_i, z_seq_comp_i, v2_pa, v3_pa, i1_pa, i2_pa, i3_pa, vh1_2, vh1_3, vh1_5, vh1_7, vh1_9, vh1_11, vh1_13, vh1_odd, vh1_even, vh1_cf, vh2_2, vh2_3, vh2_5, vh2_7, vh2_9, vh2_11, vh2_13, vh2_odd, vh2_even, vh2_cf, vh3_2, vh3_3, vh3_5, vh3_7, vh3_9, vh3_11, vh3_13, vh3_odd, vh3_even, vh3_cf, ih1_3, ih1_5, ih1_7, ih1_9, ih1_11, ih1_13, ih1_odd, ih1_even, ih1_kf, ih2_3, ih2_5, ih2_7, ih2_9, ih2_11, ih2_13, ih2_odd, ih2_even, ih2_kf, ih3_3, ih3_5, ih3_7, ih3_9, ih3_11, ih3_13, ih3_odd, ih3_even, ih3_kf
1, 2015-03-09 20:12:05, 59.97, 123.1, 122.992, 123.1, 122.5, 122.381, 122.5, 121.8, 121.749, 121.9, 0, 1.91508, 0, 0, 13.4917, 0, 0, 7.38669, 0, 19.9551, -5.54378, 226.589, 127.961, 348.94, 235.676, 1631.89, -887.699, 978.145, 235.981, 1650.68, 899.93, 2785.75, -0.02348, 0.13701, 0.14203, 0.125, 47.335, 1299.89, 3203.01, 1272600, 863619, 1272850, 863720, 1846930, 0.0148, 0.0148, 0.0123, , , , 122.4, 0.2, 0.1, 0.1, 0.6, -0.1, 0, 0, 0, 0, 0, 0, 119.9, 240.2, 92, 203.8, 160.1, , , , , , , , , , 1.428, , , , , , , , , , 1.434, , , , , , , , , , 1.427, , , , , , , , , , , , , , , , , , , , , , , , , , ,
# id, dtime, min_hz, avg_hz, max_hz, min_min_v1, avg_avg_v1, max_max_v1, min_min_v2, avg_avg_v2, max_max_v2, min_min_v3, avg_avg_v3, max_max_v3, min_min_i1, avg_avg_i1, max_max_i1, min_min_i2, avg_avg_i2, max_max_i2, min_min_i3, avg_avg_i3, max_max_i3, min_i_n, avg_i_n, max_i_n, min_l1_kw_pa, avg_l1_kw_pa, max_l1_kw_pa, min_l2_kw_pb, avg_l2_kw_pb, max_l2_kw_pb, min_l3_kw_pc, avg_l3_kw_pc, max_l3_kw_pc, min_avg_kw_t, avg_avg_kw_t, max_avg_kw_t, min_l1_kvar_qa, avg_l1_kvar_qa, max_l1_kvar_qa, min_l2_kvar_qb, avg_l2_kvar_qb, max_l2_kvar_qb, min_l3_kvar_qc, avg_l3_kvar_qc, max_l3_kvar_qc, min_avg_kvar_t, avg_avg_kvar_t, max_avg_kvar_t, min_l1_kva_sa, avg_l1_kva_sa, max_l1_kva_sa, min_l2_kva_sb, avg_l2_kva_sb, max_l2_kva_sb, min_l3_kva_sc, avg_l3_kva_sc, max_l3_kva_sc, min_avg_kva_t, avg_avg_kva_t, max_avg_kva_t, min_l1_pf_pfa, avg_l1_pf_pfa, max_l1_pf_pfa, min_l2_pf_pfb, avg_l2_pf_pfb, max_l2_pf_pfb, min_l3_pf_pfc, avg_l3_pf_pfc, max_l3_pf_pfc, min_avg_pf_t, avg_avg_pf_t, max_avg_pf_t, max_power_dmd, max_kvar_dmd, max_kva_dmd, max_kwh_imp, max_kvarh_imp, max_kwh_t, max_kvarh_t, max_kvah_t, min_v1_thd, avg_v1_thd, max_v1_thd, min_v2_thd, avg_v2_thd, max_v2_thd, min_v3_thd, avg_v3_thd, max_v3_thd, min_i1_thd, avg_i1_thd, max_i1_thd, min_i2_thd, avg_i2_thd, max_i2_thd, min_i3_thd, avg_i3_thd, max_i3_thd, p_seq_real_v, p_seq_comp_v, n_seq_real_v, n_seq_comp_v, z_seq_real_v, z_seq_comp_v, p_seq_real_i, p_seq_comp_i, n_seq_real_i, n_seq_comp_i, z_seq_real_i, z_seq_comp_i, v2_pa, v3_pa, i1_pa, i2_pa, i3_pa, vh1_2, vh1_3, vh1_5, vh1_7, vh1_9, vh1_11, vh1_13, min_vh1_odd, avg_vh1_odd, max_vh1_odd, min_vh1_even, avg_vh1_even, max_vh1_even, min_vh1_cf, avg_vh1_cf, max_vh1_cf, vh2_2, vh2_3, vh2_5, vh2_7, vh2_9, vh2_11, vh2_13, min_vh2_odd, avg_vh2_odd, max_vh2_odd, min_vh2_even, avg_vh2_even, max_vh2_even, min_vh2_cf, avg_vh2_cf, max_vh2_cf, vh3_2, vh3_3, vh3_5, vh3_7, vh3_9, vh3_11, vh3_13, min_vh3_odd, avg_vh3_odd, max_vh3_odd, min_vh3_even, avg_vh3_even, max_vh3_even, min_vh3_cf, avg_vh3_cf, max_vh3_cf, ih1_3, ih1_5, ih1_7, ih1_9, ih1_11, ih1_13, min_ih1_odd, avg_ih1_odd, max_ih1_odd, min_ih1_even, avg_ih1_even, max_ih1_even, min_ih1_kf, avg_ih1_kf, max_ih1_kf, ih2_3, ih2_5, ih2_7, ih2_9, ih2_11, ih2_13, min_ih2_odd, avg_ih2_odd, max_ih2_odd, min_ih2_even, avg_ih2_even, max_ih2_even, min_ih2_kf, avg_ih2_kf, max_ih2_kf, ih3_3, ih3_5, ih3_7, ih3_9, ih3_11, ih3_13, min_ih3_odd, avg_ih3_odd, max_ih3_odd, min_ih3_even, avg_ih3_even, max_ih3_even, min_ih3_kf, avg_ih3_kf, max_ih3_kf
1, 2015-03-25 12:05:03, 59.9351, 59.9515, 59.9651, 123, 123.165, 123.5, 122.2, 122.379, 122.7, 121.9, 121.986, 122.3, 0, 0, 0, 0, 22.8891, 0, 0, 6.69319, 0, 0, 0, 0, 0, 0, 0, 2689.78, 2741.23, 2827.1, 761.323, 767.21, 775.285, 3455.01, 3509.49, 3597.13, 0, 0, 0, -47.318, -29.5382, -16.3021, 142.391, 147.547, 152.868, 97.1515, 117.985, 131.682, 0, 0, 0, 2744.95, 2800.07, 2883.35, 799.135, 818.643, 854.545, 3545.14, 3619.77, 3699.94, 0.99903, 0.99903, 0.99903, 0.97461, 0.978048, 0.98087, 0.8978, 0.936465, 0.95534, 0.95832, 0.968614, 0.97364, 3497.05, 154.864, 3610.55, 529.2, 46.8, 529.8, 47.3, 568.1, 0.0147, 0.0149417, 0.0153, 0.0155, 0.0158617, 0.0164, 0.0138, 0.0141883, 0.0149, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122.452, -0.0783333, 0.241667, 0.103333, 0.308333, -0.0666667, 0, 0, 0, 0, 0, 0, 119.985, 240.133, 0, 121.318, 250.655, 0, 0.01061, 0, 0.003965, 0, 0, 0, 0.0131, 0.013455, 0.014, 0.0058, 0.006575, 0.007, 1.429, 1.43403, 1.435, 0, 0.0117267, 0, 0.00466333, 0, 0, 0, 0.0142, 0.0146267, 0.0152, 0.0055, 0.00624333, 0.0066, 1.435, 1.43673, 1.438, 0, 0.0110717, 0, 0, 0, 0, 0, 0.0128, 0.0132333, 0.0143, 0.0042, 0.00523333, 0.0059, 1.428, 1.42912, 1.43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
我当前的设置使用Sqlalchemy和python-MySQLdb与数据库进行通信。我需要找到一种方法来减少数据使用量,如果可能的话,不用频繁地发送数据
如果重要的话,每个远程设备都是像计算机一样的小型覆盆子。
作为参考,这是我的开发Web服务器的链接,您可以在其中查看此项目的重点。 http://104.131.181.35/live/voltsandamps 它仍在进行中。
在过去的几天里,我一直在研究MySQL压缩协议,但还没有找到一种方法来实现sqlalchemy或任何其他python数据库连接器。
我知道python_mysqldb有一个压缩标志,但我无法弄清楚如何使用它。特别是当它被用作sqlalchemy的驱动程序时,我愿意在必要时放弃。
这可能吗?如果没有,那么还有另一种解决方案可以更好地发挥作用。
任何帮助都会被贬低。
编辑:
我最终写了像@paidhima推荐的网络服务。每个设备每1-30分钟发送一次数据。数据格式基本上是压缩的json字符串,具有版本,时间戳和值数组。然后,Web服务器解压缩接收的数据并将其插入到DB中。当我第一次提出这个问题时,我对数据库和Web开发一般都知之甚少。回顾一年的时间很有趣。 Web服务的最终结果:我实现了大约10:1的压缩比(88到92%之间)。每台设备平均每天大约10-15MB。在远程设备直接连接到服务器的短暂时间之后,我开始发现这不是适用于除开发环境之外的任何其他设备的解决方案。安全问题,防火墙问题,连接丢失太多,只是一般研究导致我放弃直接连接,并编写一个简单的Web服务。
通过直接数据库连接,我能够将每台设备降低到每天约70-80 MB。这是准备好的语句,并启用了连接压缩。
Web服务是用python编写的,没有数据库交互代码,只有大约250行代码(用于客户端和服务器)。谢谢你的优秀建议@eggyal和@paidhima。我完全是自学成才,而且只有像我们这样的人提供建议和回答问题才能得到我自己的能力。
答案 0 :(得分:2)
如果您在插入每条记录时检查传输到MySQL的数据包 - 仅仅packet sniffer就可以轻松完成,因为(除非您是connecting over SSL)通信是既不加密也不压缩 - 你会注意到:
SQL INSERT
语句包含完整的列名列表,每次都传输。
浮点值以字符串形式传输,每个最多需要36个字符。
两者都会导致显着的不必要的网络利用率,而不是通过使用MySQL's binary prepared statement protocol来避免(SQL命令只能发送到服务器一次,之后只有数据值会在各自的存储中传输格式每次插入尝试。)
在SQLAlchemy支持的MySQL驱动程序中,只有Oracle的“官方”驱动程序(MySQL Connector/Python)为此功能提供了API(虽然oursql也使用该协议,但它不会重复使用重复发送的语句。
不幸的是,SQLAlchemy的mysqlconnector dialect目前没有使用这些功能。
虽然在SQLAlchemy中仍有一些可以做的事情来降低网络利用率(例如,在Core中你可以阻止传输列名的完整列表),但实际情况是你赢了用二进制预处理语句协议可以做到这一点。
因此我建议:
扩展SQLAlchemy的mysqlconnector方言以支持此类功能(更多工作,但对整个社区具有相当大的价值);或
删除SQLAlchemy(至少对于这些插入操作)而是直接使用MySQL Connector / Python驱动程序。
在采用这两种方法时,您也可以同时启用packet compression。
import time
import mysql.connector
cnx = mysql.connector.connect(user='raspberryPi_1234',
password='foobar',
host='mysql.example.com',
database='voltsandamps',
autocommit=true,
compress=true) # compress the connection
cursor = cnx.cursor(prepared=True) # this is what SQLAlchemy is missing
stmt = "INSERT INTO power_readings VALUES (" + ",".join(126*["?"]) + ")"
while true:
cursor.execute(stmt, getPowerReadings())
time.sleep(2)
如果您需要进一步降低网络利用率,可以考虑使用stored procedures封装INSERT
命令 - 不仅因为CALL myProc(...)
命令几乎总是比底层命令短INSERT
命令,但也因为它可以采用一些非常激进的技术,包括:
重新定位您的数据:如果值往往落在某个范围内,您只需要从该范围的基数传输偏移(这可能允许在期间使用较小的数据类型)然后可以在存储过程中执行 - 基于实际值的基础(并且可以使用user-defined variable来设置基本身);以及
在extremis中,可以压缩客户端上的一个数据并打包成二进制字符串,然后在服务器上解压缩和解压缩 - 从而最大化每个最后一位的使用(同样单个字符串值会导致管理更少)开销比相同聚合长度的多个单独值)。