MySQL-优化
概述 表关联查询时务必遵循 小表驱动大表 原则; 使用查询语句 where 条件时,不允许出现 函数,否则索引会失效; 使用单表查询时,相同字段尽量不要用 OR,因为可能导致索引失效,比如:SELECT * FROM table WHERE name = '手机' OR name = '电脑',可以使用 UNION 替代; LIKE 语句不允许使用 % 开头,否则索引会失效; 组合索引一定要遵循 从左到右 原则,否则索引会失效;比如:SELECT * FROM table WHERE name = '张三' AND age = 18,那么该组合索引必须是 name,age 形式; 索引不宜过多,根据实际情况决定,尽量不要超过 10 个; 每张表都必须有 主键,达到加快查询效率的目的; 分表,可根据业务字段尾数中的个位或十位或百位(以此类推)做表名达到分表的目的; 分库,可根据业务字段尾数中的个位或十位或百位(以此类推)做库名达到分库的目的; 表分区,类似于硬盘分区,可以将某个时间段的数据放在分区里,加快查询速度,可...
面向对象的特征
概述面向对象的三个基本特征是:封装、继承、多态。 封装封装最好理解了。封装是面向对象的特征之一,是对象和类概念的主要特性。封装,也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。 继承面向对象编程 (OOP) 语言的一个主要功能就是”继承”。继承是指这样一种能力:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。 多态多态性(polymorphisn)是允许你将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。简单的说,就是一句话:允许将子类类型的指针赋值给父类类型的指针。 实现多态,有二种方式,覆盖,重载。 三大特征的定义齐备,但定义回答不了两个真问题:每个特征解决什么工程问题(动机),以及它们在 Java 中的落地机制与代价。本文按”动机 → 机制 → 代价 → 设计准则”重讲三特征,并补上常被遗漏的第四特征”抽象”。 封装:把变化关进笼子动机:模块的使用者不应依赖其内部实现,否则实现一改、调用方全崩。封装把”稳定的接...
final,finally,finalize
final用于声明属性,方法和类, 分别表示属性不可变, 方法不可覆盖, 类不可继承. finally是异常处理语句结构的一部分,表示总是执行. finalize是Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,可以覆盖此方法提供垃圾收集时的其他资源回收,例如关闭文件等. JVM不保证此方法总被调用.
聊聊 MongoDB 使用场景
高伸缩性的场景MongoDB 非常适合高伸缩性的场景,它是可扩展性的表结构。基于这点,可以将预期范围内,表结构可能会不断扩展的 MySQL 表结构,通过 MongoDB 来存储,这就可以保证表结构的扩展性。 日志系统的场景日志系统数据量特别大,如果用 MongoDB 数据库存储这些数据,利用分片集群支持海量数据,同时使用聚集分析和 MapReduce 的能力,是个很好的选择。 分布式文件存储MongoDB 还适合存储大尺寸的数据,之前介绍的 GridFS 存储方案,就是基于 MongoDB 的分布式文件存储系统。 三个场景点到了 Mongo 的强项,但选型还需要另一半:它不擅长什么、以及文档模型带来的设计约束。只讲适用场景的选型文会误导人在错误场景引入 Mongo。本文补全双向边界与数据建模要点。 为什么是这三个场景:文档模型的特性映射 Schema 灵活(BSON 动态字段):表结构频繁演进的业务(商品属性、表单配置、SaaS 多租户自定义字段)——MySQL 加列要 DDL 锁表/在线变更流程,Mongo 直接写新字段 水平分片内建:分片集群(shard + mon...
选择合适的数据存储方案
选择合适的数据存储方案关系型数据库 MySQLMySQL 是一个最流行的关系型数据库,在互联网产品中应用比较广泛。一般情况下,MySQL 数据库是选择的第一方案,基本上有 80% ~ 90% 的场景都是基于 MySQL 数据库的。因为,需要关系型数据库进行管理,此外,业务存在许多事务性的操作,需要保证事务的强一致性。同时,可能还存在一些复杂的 SQL 的查询。值得注意的是,前期尽量减少表的联合查询,便于后期数据量增大的情况下,做数据库的分库分表。 内存数据库 Redis随着数据量的增长,MySQL 已经满足不了大型互联网类应用的需求。因此,Redis 基于内存存储数据,可以极大的提高查询性能,对产品在架构上很好的补充。例如,为了提高服务端接口的访问速度,尽可能将读频率高的热点数据存放在 Redis 中。这个是非常典型的以空间换时间的策略,使用更多的内存换取 CPU 资源,通过增加系统的内存消耗,来加快程序的运行速度。 在某些场景下,可以充分的利用 Redis 的特性,大大提高效率。这些场景包括缓存,会话缓存,时效性,访问频率,计数器,社交列表,记录用户判定信息,交集、并集和差集,...
ObjectId 规则
时间戳 机器码 PID 计数器 0,1,2,3 4,5,6 7,8 9,10,11 前四位是时间戳,可以提供秒级别的唯一性。 接下来三位是所在主机的唯一标识符,通常是机器主机名的散列值。 接下来两位是产生 ObjectId 的 PID,确保同一台机器上并发产生的 ObjectId 是唯一的。 前九位保证了同一秒钟不同机器的不同进程产生的 ObjectId 时唯一的。 最后三位是自增计数器,确保相同进程同一秒钟产生的 ObjectId 是唯一的。 12 字节四段式结构讲清了”如何唯一”,但 ObjectId 的设计还有三个值得展开的层面:为什么这样排布(有序性设计)、新版规范的演进(机器码随机化与计数器扩展)、以及它在工程中的用法与边界。本文补全。 结构再确认(12 字节 = 24 hex 字符) 段 字节 作用 时间戳 4 秒级 Unix 时间,大端序(高位在前) 机器标识 5(新版) 原 3 字节机器哈希 + 2 字节 PID 合并演进为 5 字节随机值(进程级) 计数器 3 进程内自增(随机初值),同秒内区分 新版(Mong...
选择合适的分布式主键方案
数据库自增长序列或字段 UUID 使用 UUID to Int64 的方法 Redis 生成 ID Twitter 的 snowflake 算法 利用 zookeeper 生成唯一 ID MongoDB 的 ObjectId 七种方案只有名字没有取舍,等于没答。分布式主键的评价维度是固定的五维:唯一性、趋势递增(对索引友好)、有序性含义、可用性/性能(生成器依赖)、信息安全性(是否可猜测)。本文按五维给七方案打分,并给出场景化选型结论。 五维评价框架 唯一性:全局不重复(底线) 趋势递增:B+Tree 聚簇索引友好(尾插无页分裂) 生成依赖:是否需要中心组件(DB/Redis/ZK),依赖即单点与延迟来源 吞吐与延迟:本地生成(ns 级)vs 远程生成(ms 级/批量号段摊销) 安全性:是否暴露业务量/时间(可枚举猜测) 七方案逐一评析1. 数据库自增(单库):递增完美、唯一性靠单库;但分库分表后冲突,且暴露业务量、生成依赖 DB 写。单库时代的最优解,分布式的起点问题。 2. 多库自增(步长法):库 1 发 1,3,5…、库 ...
limit 20000 加载很慢怎么解决
MySQL 的性能低是因为数据库要去扫描 N + M 条记录,然后又要放弃之前 N 条记录,开销很大 解决思路: 前端加缓存,或者其他方式,减少落到库的查询操作,例如某些系统中数据在搜索引擎中有备份的,可以用 es 等进行搜索 使用延迟关联,即先通用 limit 得到需要数据的索引字段,然后再通过原表和索引字段关联获得需要数据 select a.* from a,(select id from table_1 where is_deleted='N' limit 100000,20) b where a.id = b.id 从业务上实现,不分页如此多,例如只能分页前 100 页,后面的不允许再查了 不使用 limit N,M, 而是使用 limit N,即将 offset 转化为 where 条件。 慢的根因(扫 N+M 扔 N)与四条思路都对,但还缺三块:为什么”扔 N 条”这么贵(回表视角)、游标法(keyset)的完整写法与适用边界、以及各方案的组合策略。本文补全成深分页优化手册。 根因深挖:offset 的两重代价LIMIT 100000, ...
聚集索引与非聚集索引的区别
聚集索引一个表只能有一个,而非聚集索引一个表可以存在多个 聚集索引存储记录是物理上连续存在,而非聚集索引是逻辑上的连续,物理存储并不连续 聚集索引:物理存储按照索引排序;聚集索引是一种索引组织形式,索引的键值逻辑顺序决定了表数据行的物理存储顺序 非聚集索引:物理存储不按照索引排序;非聚集索引则就是普通索引了,仅仅只是对数据列创建相应的索引,不影响整个表的物理存储顺序. 索引是通过二叉树的数据结构来描述的,我们可以这么理解聚簇索引:索引的叶节点就是数据节点。而非聚簇索引的叶节点仍然是索引节点,只不过有一个指针指向对应的数据块。 五条特征准确,但还差三块把区别变成可用知识:回表与覆盖索引的代价模型、聚簇键的选择原则、以及”物理连续”的准确含义(页内连续而非物理相邻)。本文补全。 结构再确认:叶节点存什么 聚簇索引(clustered):叶节点 = 完整行数据;表数据按聚簇键组织成一棵 B+Tree——“表即索引” 非聚簇索引(secondary):叶节点 = 索引键 + 聚簇键值(InnoDB);是独立于表数据的第二棵树 一个表只能有一个聚簇索引的原因由此自...
为什么要用 B-Tree
一般来说,索引本身也很大,不可能全部存储在内存中,因此索引往往以索引文件的形式存储的磁盘上。这样的话,索引查找过程中就要产生磁盘 I/O 消耗,相对于内存存取,I/O 存取的消耗要高几个数量级,所以评价一个数据结构作为索引的优劣最重要的指标就是在查找过程中磁盘 I/O 操作次数的渐进复杂度。换句话说,索引的结构组织要尽量减少查找过程中磁盘 I/O 的存取次数。 “以磁盘 IO 次数为评价标尺”是全文的题眼。顺着这把标尺,可以推导出 B-Tree/B+Tree 的每一个设计选择:为什么是多路而非二叉、为什么节点大小等于页、为什么数据沉到叶子。本文完成这条推导链,并对照被淘汰的候选结构。 标尺:一次磁盘 IO 的代价模型 内存访问 ~100ns,磁盘随机 IO ~10ms(机械)/ ~0.1ms(SSD)——差 3-5 个数量级 磁盘按页/块(InnoDB 16KB)为单位读写:读一个字节与读一页成本几乎相同 推论一:算法复杂度要换算成 IO 次数才有意义;log2(N) 次 IO 的二叉树可能输给 log1000...















