求各位大佬给些报表优化的思路?

2023-01-02 09:45:59 +08:00
 sunmoon1983

现在客户要求这么一张报表 横向为年龄 竖向为项目名称 有各种条件每次客户进入页面都要点击一下开始分析,报表生成起来很慢,现在要求优化,加上了缓存,但是第一次生成报表的时候还是需要等待,想用计划任务跑一下,但是想到了各种搜索条件组合起来有很多情况,没有实施,求优化思路!

当前表结构

CREATE TABLE `xx_table1` (
  `id` bigint NOT NULL,
  `code` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '编号',
  `full_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '姓名',
  `gender` tinyint NOT NULL DEFAULT '0' COMMENT '性别',
  `age` smallint DEFAULT '0' COMMENT '年龄',
  `idcard` varchar(33) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '身份证号',
  `resident_address` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '常驻地址',
  `resident_address_code` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '常驻地址行政编码',
  `registered_address` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '户籍地址',
  `registered_address_code` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '户籍地址行政编码',
  `birthday` date DEFAULT '0000-00-00' COMMENT '生日',
  `dead_date` datetime DEFAULT NULL COMMENT '死亡日期',
  `dead_place_code` bigint NOT NULL DEFAULT '0' COMMENT '死亡地点',
  `family_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '家属姓名',
  `family_tel` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '家属联系电话',
  `created_at` datetime DEFAULT NULL COMMENT '创建时间',
  `created_by` bigint NOT NULL COMMENT '创建人',
  `is_audit` tinyint NOT NULL DEFAULT '1' COMMENT '是否审核',
  `audit_by` bigint DEFAULT NULL COMMENT '审核人',
  `audit_at` datetime DEFAULT NULL COMMENT '审核时间',
  `year` int NOT NULL DEFAULT '0' COMMENT '年份',
  `item_id` int NOT NULL DEFAULT '0' COMMENT '项目 id',
  `area_code` bigint DEFAULT '0' COMMENT '地区代码',
  PRIMARY KEY (`id`) USING BTREE,
  KEY `p_fi_idx` (`full_name`,`idcard`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC COMMENT='XX 表';

索引还没加

数据量大于 100W!

想到了把数据跑成单表,但是没做过,不知道要怎么写,不知道单表要怎么建,求大老指点

4871 次点击
所在节点    MySQL
44 条回复
dode
2023-01-02 14:23:04 +08:00
这是疫情的系统啊😯
nandaye
2023-01-02 16:14:57 +08:00
首先看你指标是可加指标还是不可加指标,不可加基本只能加资源缓存之类的方案;可加指标就按筛选条件最小粒度聚合一次,查询时用筛选条件基于聚合数据做二次聚合
git00ll
2023-01-02 16:35:28 +08:00
一百万而已,后期预期会增加到多少。 一百万的话遍历一遍在代码里也把报表弄出来了
c6h6benzene
2023-01-02 16:52:58 +08:00
@sunmoon1983 其实我想说的是你后端先把最小粒度的全部数据缓存起来,把汇总之类的维度计算全部放在前端完成。

报表的前端呈现是自己的写的吗,还是要利用什么其他现有的报表工具?

另外微软那一套 BI 架构的话,有个东西叫 Cube (多维数据集),就是用来处理这种会有多个维度数据需求的应用的。
sunmoon1983
2023-01-02 17:21:18 +08:00
@c6h6benzene 前端自己写的,`最小粒度的全部数据` 这个要怎么解释?现在就是这里不太明白,第一次做报表,不太懂
jiangwentx
2023-01-02 19:19:58 +08:00
1 楼说的的确是个思路,但客户想要看各种组合,显然穷举很慢很累,而且一直跟着屁股后面改代码不现实,elasticsearch 聚合出所有情况,至于客户要看完整报表,那就用定时程序查 es 的各种情况总量写入表中,然后只要查表供前端展示即可。(没人力客户没预算当我没说)
yufeng0681
2023-01-02 20:25:48 +08:00
100 万数据 想办法变成 1W 级别的数据(临时表方案) ,基于 1W 数据做查询就快了。
做好同步操作, 看甲方的要求,按天、按周同步一次; 也支持手动同步。
jones2000
2023-01-02 22:06:43 +08:00
@Chad0000 就这几百 W 的数据量, 买一台 20W 的物理机, 直接装 mysql , 用到的数据索引建完基本就够了。要什么优化,加配置就够了。
makdon
2023-01-02 22:35:44 +08:00
之前做过类似的需求,用的 apache druid ,非常适合这种场景
redbridge
2023-01-02 22:54:19 +08:00
如果用户查询组合不复杂,而且重复性高的话,可以在用户每次调用时候把查询条件自动记下来,自动生成定时任务。当然如果用户查询情况太多了就不太适合。
yasea
2023-01-02 23:05:06 +08:00
@sunmoon1983
select
gender
,age
,year
,sum(xxx)xxx
,count(xxx)xxx
from xx_table1
group by gender,age,year
这个是一个底层的汇总表, 可以直接放到内存进行查询统计,如果这个表数据量太大,可以再做切割,然后在前端做查询缓存,在生成上面这个汇总的表时候,也可以直接根据可能的查询条件将把数据生成到前端进行缓存。
xuanbg
2023-01-03 08:32:35 +08:00
把完整的透视数据跑出来存起来,然后无非就是条件查询而已。
NizumaEiji
2023-01-03 10:03:25 +08:00
hbase ?
sunmoon1983
2023-01-03 10:04:56 +08:00
@xuanbg 现在我就是想不明白,这个完整的数据要怎么跑,是把每个条件都组合一次,去跑数据,还是要怎么跑呢?
sunmoon1983
2023-01-03 10:06:20 +08:00
@xuanbg 比如,上面图中的条件有户籍,性别,年份,那个,我就要`城市户籍+男+2022`跑一次,下面再用`城市户籍+女+2022`跑一次,然后`农村户籍+性别(男、女)+每一年(从今年到 2010 年)`都跑一次存到库中,是这样吗?后面还要加上地区,好多条件呀,不敢想象
xuanbg
2023-01-03 11:35:19 +08:00
@sunmoon1983 你先忘记条件,没有任何条件,不就是全部了吗?然后,根据条件分组,就是多维度数据。这个时候,可以直接出,也可以汇总出,具体看你条件分组的数据是否是正交的。总之,只要结果正确就行。
7911364440
2023-01-03 11:41:22 +08:00
先根据"最小统计粒度"计算下每个年龄段的数量,查询时根据用户选择的统计条件只需要单独计算下这几个条件的数量就好。
比如要查询 "城市户籍+男+2022" = 2022 总数 - 非城市户籍数量 - 非男性数量
wxf666
2023-01-03 12:12:22 +08:00
@sunmoon1983 你要多少秒内出结果呢?

@7911364440 比如,100W 数据里,只有 1 个城市户籍、1 个男性、1 个 2022 的,那算式是 1 - (100W - 1) - (100W - 1) ?还是咋算的?
warcraft1236
2023-01-03 13:27:21 +08:00
为什么不考虑中间夹一层呢?不要直接读 mysql ,可以搞一个比如 es 这种的东西,他的查询应该会快很多,100w 这个量级上应该比 mysql 快很多
lazyfighter
2023-01-03 14:37:13 +08:00
目测提前算就行, 比如今天算出来昨天的数据, 把结果直接存起来, 基本上 T-1 之前的数据不会变化的

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/906010

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX