一 平常经常使用外键和外键和级联吗,可以说说你对它们的理解吗?
对于外键和级联,阿里巴巴开发手册这样说到:
【强制】不得使用外键与级联,一切外键概念必须在应用层解决。
说明:以学生和成绩的关系为例,学生表中的 student_id 是主键,那么成绩表中的 student_id 则为外键。如果更新学生表中的 student_id,同时触发成绩表中的 student_id 更新,即为级联更新。外键与级联更新适用于单机低并发,不适合分布式、高并发集群;级联更新是强阻塞,存在数据库更新风暴的风 险;外键影响数据库的插入速度
为什么不要用外键呢?大部分人可能会这样回答:
-
增加了复杂性: a.每次做DELETE 或者UPDATE都必须考虑外键约束,会导致开发的时候很痛苦,测试数据极为不方便;b.外键的主从关系是定的,假如那天需求有变化,数据库中的这个字段根本不需要和其他表有关联的话就会增加很多麻烦。
-
增加了额外工作: 数据库需要增加维护外键的工作,比如当我们做一些涉及外键字段的增,删,更新操作之后,需要触发相关操作去检查,保证数据的的一致性和正确性,这样会不得不消耗资源; (个人觉得这个不是不用外键的原因,因为即使你不使用外键,你在应用层面也还是要保证的。 所以,我觉得这个影响可以忽略不计。 )
-
外键还会因为需要请求对其他表内部加锁而容易出现死锁情况;
-
对分不分表不友好 : 因为分库分表下外键是无法生效的。
-
......
-
保证了数据库数据的一致性和完整性;
-
级联操作方便,减轻了程序代码量;
-
......
-
UUID: 不适合作为主键,因为太长了,并且无序不可读,查询效率低。 比较适合用于生成唯一的名字的标示比如文件的名字。
-
数据库自增 id : 两台数据库分别设置不同步长,生成不重复ID的策略来实现高可用。 这种方式生成的 id 有序,但是需要独立部署数据库实例,成本高,还会有性能瓶颈。
-
利用 redis 生成 id : 性能比较好,灵活方便,不依赖于数据库。 但是,引入了新的组件造成系统更加复杂,可用性降低,编码更加复杂,增加了系统成本。
-
Twitter的snowflake算法 : Github 地址: https://github.com/twitter-archive/snowflake。
-
美团的Leaf分布式ID生成系统 : Leaf 是美团开源的分布式ID生成器,能保证全局唯一性、趋势递增、单调递增、信息安全,里面也提到了几种分布式方案的对比,但也需要依赖关系数据库、Zookeeper等中间件。 感觉还不错。 美团技术团队的一篇文章: https://tech.meituan.com/2017/04/21/mt-leaf.html 。
-
......
float b = 0.9f - 0.8f;
System.out.println(a);// 0.100000024
System.out.println(b);// 0.099999964
System.out.println(a == b);// false
BigDecimal b = new BigDecimal("0.9");
BigDecimal c = new BigDecimal("0.8");
BigDecimal x = a.subtract(b);// 0.1
BigDecimal y = b.subtract(c);// 0.1
System.out.println(x.equals(y));// true
BigDecimal a = new BigDecimal("1.0");
BigDecimal b = new BigDecimal("0.9");
System.out.println(a.compareTo(b));// 1
BigDecimal n = m.setScale(3,BigDecimal.ROUND_HALF_DOWN);
System.out.println(n);// 1.255
-
按照流的流向分,可以分为输入流和输出流;
-
按照操作单元划分,可以划分为字节流和字符流;
-
按照流的角色划分为节点流和处理流。
-
InputStream/Reader: 所有的输入流的基类,前者是字节输入流,后者是字符输入流。
-
OutputStream/Writer: 所有输出流的基类,前者是字节输出流,后者是字符输出流。