V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX  ›  BiChengfei  ›  全部回复第 21 页 / 共 21 页
回复总数  419
1 ... 12  13  14  15  16  17  18  19  20  21  
2021-09-18 11:04:29 +08:00
回复了 git00ll 创建的主题 Java h2database 最近一版还是 2019 年更新的,似乎热度也不怎么高
h2 derby
Mybatis 源码的单元测试用的 derby,够用了
2021-09-17 10:25:56 +08:00
回复了 SirCarol 创建的主题 程序员 分布式系统数据一致性问题
分布式系统中的 CAP 理论,你这里需要保证 CP,不过只用关注 C,一致性,Consistency,技术方案一般都要搭配业务和公司情况,只要能解决问题就是好方案,这个也只能给你提供思路
```
1. 开启 MySQL 事务
2. 写入 MySQL;
3. 写入 云平台,并判断是否成功
3.1 写入成功,提交 MySQL 事务,接口返回成功
3.2 写入失败,回滚 MySQL 事务,接口返回失败
```
对于历史数据,直接用工具同步。对于增量数据,可以想象上述方法,借用事务的思路,写入的时候,双写成功,接口才会返回插入成功,否则事务回滚,这样应该保存了数据强一致性。

对于楼上提出的用 DataX 或者 flinkX,这些工具只是做数据同步的工作,数据延迟较大,并且好像也不能保证一致性

欢迎大家提出意见
牛牛牛,不过生成的文档风格,不太习惯
2021-09-07 11:37:52 +08:00
回复了 git00ll 创建的主题 MySQL 在一个事务内插入大量数据会怎么样
产品经理都不敢提的需求
不过可以思考下 insert into A_bak select * from A
2021-09-07 10:46:10 +08:00
回复了 mugglezzz 创建的主题 问与答 请教大家一个 SQL 的问题
@zhangyaxiao072 不知道,很少用这个,楼主试一下就知道了,小问题
2021-09-07 10:38:04 +08:00
回复了 mugglezzz 创建的主题 问与答 请教大家一个 SQL 的问题
union 如果可以,这个语句还可以优化,考虑到 id 、fullname 、shortname,这三种匹配数据量的问题,在子语句中进行排除重复数据
2021-09-07 10:29:29 +08:00
回复了 mugglezzz 创建的主题 问与答 请教大家一个 SQL 的问题
左连接,左边表不能为 null,右边表可能为 null,你 sql 中把右边表为 null 的情况排除,那么就是内连接,所以改为 inner join
因为 mysql 会对你的 sql 进行解析优化,再加上有 is not null,所以以前的语句能不能命中索引不知道,不知道有人能有理有据的科普下吗
2021-09-07 10:22:57 +08:00
回复了 mugglezzz 创建的主题 问与答 请教大家一个 SQL 的问题
信息太少,暂不知道怎么优化,
-- 第一种 sql 似乎可以简写下,不知道会不会命中索引
```
select A.*, B.* from A
inner join B on A.ID = B.ID or A.FullName = B.FullName or A.ShortName = B.ShortName
```

-- 第二种用 union 拼接,不知道这样去重可以吗,也不知道会不会命中索引
```
select distinct * from (
select
A.*,
B.*
from A
inner join B on A.ID = B.ID
union
select
A.*,
B.*
from A
inner join B on A.FullName = B.FullName
union
select
A.*,
B.*
from A
inner join B on A.ShortName = B.ShortName) temp
```
@l00t 之前的不对是因为没有考虑缺考吗,大意了

-- t_student 、t_course 全连接,然后左连接成绩表,缺考就为 null
select
a 。id,
a 。name
from t_student a
left join t_course b on true
left join t_grade c on a 。id = c 。student_id and b 。id = c 。course_id
group by a 。id
having min(c 。grade) >= 80;

-- t_grade 左连接 t_student,通过学生 id 分组,然后最低分和参考课程数过滤
select
a 。id,
b 。name
from t_grade a
left join t_student b on a 。student_id = b 。id
group by a 。student_id
having
min(a 。grade) >= 80
and count(a 。course_id) = (select count(*) from t_course);

第一种是第一想法,但会占用额外的内存,第二种会好很多

请不要在每一个回复中都包括外链,这看起来像是在 spamming
我只能把点换成句号
@l00t 这不是本科《数据库原理》中的 demo 吗?我会写,我是不是面试通过了,嘿嘿嘿
create table t_student (
id integer primary key ,
name varchar(40)
);

create table t_course (
id integer primary key ,
course varchar(40)
);

create table t_grade (
id integer primary key ,
student_id integer,
course_id integer,
grade integer
);

insert into t_student(id, name) values (1, '张三');
insert into t_student(id, name) values (2, '王五');
insert into t_student(id, name) values (3, '小李');
insert into t_student(id, name) values (4, '王华');

insert into t_course(id, course) values ( 1, '数学' );
insert into t_course(id, course) values ( 2, '语文' );
insert into t_course(id, course) values ( 3, '英语' );
insert into t_course(id, course) values ( 4, '化学' );
insert into t_course(id, course) values ( 5, '物理' );

insert into t_grade(id, student_id, course_id, grade) values ( 1, 1, 1, 100 );
insert into t_grade(id, student_id, course_id, grade) values ( 2, 1, 2, 80 );
insert into t_grade(id, student_id, course_id, grade) values ( 3, 1, 3, 10 );
insert into t_grade(id, student_id, course_id, grade) values ( 4, 1, 4, 100 );
insert into t_grade(id, student_id, course_id, grade) values ( 5, 1, 5, 100 );

insert into t_grade(id, student_id, course_id, grade) values ( 6, 2, 1, 100 );
insert into t_grade(id, student_id, course_id, grade) values ( 7, 2, 1, 100 );
insert into t_grade(id, student_id, course_id, grade) values ( 8, 2, 1, 100 );
insert into t_grade(id, student_id, course_id, grade) values ( 9, 2, 1, 100 );
insert into t_grade(id, student_id, course_id, grade) values ( 10, 2, 1, 100 );

select
a.student_id,
b.name
from t_grade a
left join t_student b on a.student_id = b.id
left join t_course c on a.course_id = c.id
group by a.student_id
having min(a.grade) >= 80
2021-08-25 10:09:32 +08:00
回复了 BiChengfei 创建的主题 Java Mybatis 枚举类型处理器扩展之 EnumHandler
@lululau 参考 mybatis 和 spring mvc 对枚举的处理,枚举名(字符串)应该是最标准的
2021-08-24 18:39:27 +08:00
回复了 BiChengfei 创建的主题 Java Mybatis 枚举类型处理器扩展之 EnumHandler
@siweipancc 是的,只需要实现接口 TypeHandler 就可
如果是学习,建议自定义枚举类型处理器,很简单的
但真实项目中,这样还是有点点麻烦,我思考了一两周,也和同事讨论过,然后觉得这个扩展有意义,就做了

现在微服务当道,我们项目经常会被拆分成很多子系统,就算我们自定义,最后为了高聚合,也会提取出来,形成一个单独的模块
2021-08-24 17:36:46 +08:00
回复了 BiChengfei 创建的主题 Java Mybatis 枚举类型处理器扩展之 EnumHandler
@jorneyr 哈哈哈,写的越多,bug 越多,不敢多写,不过后续会慢慢完善
2021-08-24 14:58:15 +08:00
回复了 BiChengfei 创建的主题 Java Mybatis 枚举类型处理器扩展之 EnumHandler
这算是一个小插件,来源是公司业务代码的需要,参考了一篇博客: https://segmentfault.com/a/1190000010755321 (简单易懂)
2021-08-24 14:56:20 +08:00
回复了 BiChengfei 创建的主题 Java Mybatis 枚举类型处理器扩展之 EnumHandler
@Martin9 不知道啊,没用过 mybatis plus,有时间看看
2021-07-06 11:35:15 +08:00
回复了 DavZhn 创建的主题 MySQL 不懂就问: mysql 中大数据量日环比计算时间太久
@DavZhn
昨天的思路不太好,缓存你可以考虑。
今天有另一个思路,不知道你表中的 day 的数据格式,不过可以加工下,然后加个 tomorrow 字段,再创建合适索引,查询语句把 order by 去掉(因为 explain 中有 Using filesort,排序可以前端或者后端做一下,不过影响好像不大)
如果原始表结构不能变动,那就新建一个专门来查询的表,以前我们大数据量就是构件冗余表,专门用来查询
本地测试 DDL:
-- day 、add_day 字段都是 yyyy-MM-dd 格式,本地有 6000 条数据,这样改造后,效率从 20 s 变成了 300 ms 内
CREATE TABLE `t_v2_data`
(
`id` int(11) NOT NULL AUTO_INCREMENT,
`day` varchar(200) DEFAULT NULL,
`R11` varchar(200) DEFAULT NULL,
`add_day` varchar(200) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `index_day_R11_add_day` (`day`, `R11`, `add_day`)
) ENGINE = InnoDB AUTO_INCREMENT = 6001 DEFAULT CHARSET = latin1;

查询语句:
SELECT
DATE_FORMAT(t.day, '%d'),
t.R11 as num,
y.R11 ynum,
CASE WHEN y.R11 IS NULL OR y.R11 = 0 THEN 0.00 ELSE round((t.R11/y.R11)-1, 2 ) END cc
FROM
(SELECT day, R11 FROM t_v2_data ) t
left JOIN ( SELECT add_day, R11 FROM t_v2_data ) y ON t.day = y.add_day
where t.day between '2020-5-01' and '2020-5-30'
2021-07-05 11:36:02 +08:00
回复了 DavZhn 创建的主题 MySQL 不懂就问: mysql 中大数据量日环比计算时间太久
我觉得:
1. 可以做一个缓存视图(view),用来保存统计结果,实现:写一个存储过程, 当有数据新增的时候执行统计 sql(你发出来的那个), 然后代码直接从视图中查询结果 -- 这种就是缓存的思路,redis 缓存也可以
2. day 字段加索引(没有测试,我觉得这样会快一点)
```
SELECT
DATE_FORMAT(t.day, '%d'),
t.R11 as num,
y.R11 ynum,
CASE WHEN y.R11 IS NULL OR y.R11 = 0 THEN 0.00 ELSE round((t.R11/y.R11)-1, 2 ) END cc
FROM
(SELECT STR_TO_DATE(day,'%Y-%m-%d') as day, CONVERT(R11, DECIMAL) as R11 FROM 原始数据表 ) t
left JOIN ( SELECT date_add(STR_TO_DATE(day,'%Y-%m-%d'), INTERVAL 1 DAY) as tomorrow, CONVERT(R11, DECIMAL) as R11 FROM 原始数据表 ) y ON t.day = y.tomorrow
where t.day BETWEEN #{startTime} and #{endTime}
order by t.day
```

几百万条数据对 mysql 来说洒洒水啊,完全有优化空间
1 ... 12  13  14  15  16  17  18  19  20  21  
关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5193 人在线   最高记录 6679   ·     Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 · 26ms · UTC 01:26 · PVG 09:26 · LAX 17:26 · JFK 20:26
Developed with CodeLauncher
♥ Do have faith in what you're doing.