Php 在MySQL集群中导入和报告较大的数据集

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报告需要很长时间

我们有一个MySQL(mariaDB/Galera)集群,在一个表中包含数十亿个唯一的数据点。 我们需要将该表迁移到一个新的表中,以排序需要很长时间的双项,我们在这方面受到限制。下一步是为给定的时间窗口生成报告,并生成相应NAS(现实世界中的路由器/a位置)的UUID,以及反复出现或切换NAS的用户的唯一ID(MAC)

MySQL(mariaDB/Galera)数据库目前的大小约为25GB,这应该不是问题。但是,结合UUIDs nase/locations查询用户的uid/mac报告需要很长时间

桌子结构的布局如图所示。一个是实际表,两个是可能的优化。但我真的不知道这是否有用

我们的DB方法是正确的还是应该使用不同的方法(DB、表结构、堆栈等等)(开放供建议)

迁移的查询(非常慢)如下所示:

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字节)

我认为您在转换过程中有三个问题需要解决:

  • 有效地将当前模式更改为更好的模式。假设它有旧的、不变的行,您可以在后台执行此操作
  • 快速完成最后一步。(实际上,我们将在最后完成此操作。)
  • 将摄取更改为新格式
  • 第0步:抓取最新的时间戳,以便在花时间执行第1步后知道在哪里执行第2步和第3步

    步骤1:要构建
    用户
    站点
    ,可能只需要

    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/MEDIUMINT
    id
    。相反,请参见上面的链接

    如果每秒不超过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('...') ),
               '...', '...'
               );