Php 在MySQL集群中导入和报告较大的数据集
我们有一个MySQL(mariaDB/Galera)集群,在一个表中包含数十亿个唯一的数据点。 我们需要将该表迁移到一个新的表中,以排序需要很长时间的双项,我们在这方面受到限制。下一步是为给定的时间窗口生成报告,并生成相应NAS(现实世界中的路由器/a位置)的UUID,以及反复出现或切换NAS的用户的唯一ID(MAC) MySQL(mariaDB/Galera)数据库目前的大小约为25GB,这应该不是问题。但是,结合UUIDs nase/locations查询用户的uid/mac报告需要很长时间 桌子结构的布局如图所示。一个是实际表,两个是可能的优化。但我真的不知道这是否有用 我们的DB方法是正确的还是应该使用不同的方法(DB、表结构、堆栈等等)(开放供建议) 迁移的查询(非常慢)如下所示:Php 在MySQL集群中导入和报告较大的数据集,php,mysql,mariadb,report,galera,Php,Mysql,Mariadb,Report,Galera,我们有一个MySQL(mariaDB/Galera)集群,在一个表中包含数十亿个唯一的数据点。 我们需要将该表迁移到一个新的表中,以排序需要很长时间的双项,我们在这方面受到限制。下一步是为给定的时间窗口生成报告,并生成相应NAS(现实世界中的路由器/a位置)的UUID,以及反复出现或切换NAS的用户的唯一ID(MAC) MySQL(mariaDB/Galera)数据库目前的大小约为25GB,这应该不是问题。但是,结合UUIDs nase/locations查询用户的uid/mac报告需要很长时间
INSERT INTO `metric_macs` m
(`uuid`,`shortname`,`mac`,`start`,`stop`,`duration`)
VALUES
SELECT uuid, shortname, mac, a, b, duration
FROM import i
ON DUPLICATE KEY update m.id = m.id
查询唯一用户:
SELECT DISTINCT mac FROM `metric_macs` WHERE uuid in ('xxxx','yyyyy') and ( start BETWEEN '2020-01-01' and '2020-02-01' or stop BETWEEN '2020-01-01' and '2020-02-01') ;
所有数据集的计数
查询经常性用户:
SELECT id FROM `metric_macs`
WHERE uuid in ('xxxx','yyyyy')
and ( start BETWEEN '2020-01-01' and '2020-02-01'
or stop BETWEEN '2020-01-01' and '2020-02-01')
GROUP BY `mac`, `uuid`
HAVING COUNT(*) > 1
所有数据集的计数
查询唯一位置切换用户:
SELECT uuid,mac FROM `metric_macs`
WHERE uuid in ('xxxx','yyyyy')
and ( start BETWEEN '2020-01-01' and '2020-02-01'
or stop BETWEEN '2020-01-01' and '2020-02-01')
GROUP BY `mac`, `uuid`
在这之后,php被用来统计具有两个以上不同UUID的所有用户
该列表每15分钟更新一次,其中包含连接到NAS的UID(MAC)列表,该列表在过去20分钟内检查给定UID(MAC)的活动。如果有,我们更新最后一个条目的停止计数,增加15分钟,并开始计算增益
抱歉弄得一团糟。我们对这种报告生成相当陌生。优化数据库或查询以实现近即时报告的可能方法有哪些
谢谢
编辑:
最好不要使用36字节的ID。但是,不要在8字节处停止;您可能不需要超过4个字节(
INT UNSIGNED
,最大值或40亿)或3个字节(MEDIUMINT UNSIGNED
,最大值为16M)
此时,请删除破折号并取消UUID的显示,以便它们可以放入二进制(16)
(16字节)
我认为您在转换过程中有三个问题需要解决:
用户
和站点
,可能只需要
INSERT INTO users (user_id)
SELECT UUID2BIN(userID)
FROM ( SELECT DISTINCT userID ) FROM log;
(对于电台也类似)
有关转换UUID的信息,请参见以下内容:
这可能需要一些时间,但它可以有效地执行重复数据消除
在填写步骤2之前,让我先讨论步骤3
步骤3:如果摄取率为“高”,请参阅此以了解乒乓球暂存表和批量标准化等的详细信息:
然而,你的摄取率可能没有那么快。不要使用IODKU,使用LAST\u INSERT\u ID
从用户
和站点
获取ID。它将“烧掉”id,并威胁溢出您的INT/MEDIUMINTid
。相反,请参见上面的链接
如果每秒不超过100(HDD)或每秒不超过1000(SSD),则在获得必要ID的同时插入时间\u表可以是一个简单的INSERT
INSERT INTO time_table (user_id, station_id, start_time, stop_time)
VALUES (
( SELECT id FROM users WHERE userID = uuid2bin('...') ),
( SELECT id FROM stations WHERE userID = uuid2bin('...') ),
'...', '...'
);
回到步骤2。您在旧表中保存了一堆行。你还保存了这些的开始日期。因此,从log
执行批量规范化和批量插入,就像我在链接中讨论的“暂存表”一样
这将允许您在新表“不完整”时,以零停机时间和少量时间进行转换
我没有谈到为什么“报告需要很长时间”。我需要查看选项
。同时,这里有两个想法:
如果您构建了新的类似INT的id,请按日期对它们进行排序,以便它们至少按时间顺序排序,因此对于某些类型的查询更好地进行集群
通常,构建和维护“汇总表”可以让报表运行得更快。看
“经常性用户查询:”存在多个查询性能问题。除非我的方法不充分,否则我不想深入细节。我认为MAC地址是17个字符,而不是36个字符。并且在您的模式中没有提到metric\u macs
。请在您的问题中包括SHOW CREATE TABLE
;不要使用图像。我认为从选择插入时不允许使用关键字值
。嗨,里克·詹姆斯,谢谢你的回答,我们将在周一进行调查。我将CREAT TABLE附加到了我的第一篇文章。@expired-在中的位置总是有2个UUID吗?哪个更具选择性——uuid还是日期范围?它始终是两者的组合。将度量、macs、uuid、索引作为冗余;当索引越长越好时,优化器可能会使用它。
INSERT INTO time_table (user_id, station_id, start_time, stop_time)
VALUES (
( SELECT id FROM users WHERE userID = uuid2bin('...') ),
( SELECT id FROM stations WHERE userID = uuid2bin('...') ),
'...', '...'
);