Mysql-一些问题

分库分表

一、分库分表原因
单机的存储能力、连接数有限
单表数据量百万以内,可通过添加从库、优化索引提升性能
数据量千万以上,性能下降。
为减少数据库负担、提高数据库响应速度、缩短查询时间

二、以大化小
1、垂直切分
垂直分库:基于业务分类。
垂直分表:给予数据表的列(大表拆小表)

2、水平切分
库内分表:子表在同一个数据库实例中(解决单一表大数据量过大,但仍在竞争同一个物理机的CPU、内存、网络IO)
分库分表:解决高并发单库数据量过大问题,提升系统稳定性和负载能力;跨分片事务一致性难以保证,跨库join性能差,扩容难度和维护大

三、数据存储
1、根据取值范围
2、hash取模

四、坑
1、事务一致性问题
2、分页、排序的坑
3、全局唯一主键问题

五、分库分表中间件
sharding-jdbc(当当)
TSharding(蘑菇街)
Atlas(奇虎360)
Cobar(阿里巴巴)
MyCAT(基于Cobar)
Oceanus(58同城) Vitess(谷歌)

转自:https://mp.weixin.qq.com/s/-5tZEjUf0J9KUSm6uqnh9A

可参考:https://mp.weixin.qq.com/s?__biz=MjM5ODI5Njc2MA==&mid=2655832798&idx=2&sn=52ff78a8502e7044cb108bf2719ca525&chksm=bd7487098a030e1f00787d50d10ed1360c5adfdad1bd61630195cc3932579ee05a2d3eaa5810&scene=21#wechat_redirect

 

 

千万级别数据的表分页优化

当进行分页时,MySQL 并不是跳过 offset 行,而是取 offset+N 行,然后放弃前 offset 行,返回 N 行。
PS:当 offset 特别大时,效率非常低

使用书签
用书签记录上次取数据的位置,过滤掉部分数据
如下面语句:SELECT id, name, description FROM film ORDER BY name LIMIT 1000, 10;
可以改为:SELECT id, name, description FROM film WHERE name > 'begin' ORDER BY name LIMIT 10;
name为上次分页后的最大值,注意这种场景只适用于不存在重复值的场景。

延迟关联
延迟关联:通过使用覆盖索引查询返回需要的主键,再根据主键关联原表获得需要的数据
SELECT id, name, description FROM film ORDER BY name LIMIT 100,5;
id是主键值,name上面有索引。这样每次查询的时候,会先从name索引列上找到id值,然后回表,查询到所有的数据。可以看到有很多回表其实是没有必要的。完全可以先从name索引上找到id(注意只查询id是不会回表的,因为非聚集索引上包含的值为索引列值和主键值,相当于从索引上能拿到所有的列值,就没必要再回表了),然后再关联一次表,获取所有的数据
因此可以改为

SELECT film.id, name, description FROM film 
JOIN (SELECT id from film ORDER BY name LIMIT 100,5) temp
ON film.id = temp.id

倒序查询
假如查询倒数最后一页,offset可能会非常大
SELECT id, name, description FROM film ORDER BY name LIMIT 100000, 10;
改成倒序分页,效率是不是快多了?
SELECT id, name, description FROM film ORDER BY name DESC LIMIT 10;

转自:https://mp.weixin.qq.com/s/fy54wH513VHRu8W19gv8Wg

 

MySql优化

优化成本:硬件>系统配置>数据库表结构>SQL 及索引
优化效果:硬件<系统配置<数据库表结构<SQL 及索引

对于MySQL层优化一般遵从五个原则:

  • 减少数据访问:设置合理的字段类型,启用压缩,通过索引访问等减少磁盘 IO。
  • 返回更少的数据:只返回需要的字段和数据分页处理,减少磁盘 IO 及网络 IO。
  • 减少交互次数:批量 DML 操作,函数存储等减少数据连接次数。
  • 减少服务器 CPU 开销:尽量减少数据库排序操作以及全表查询,减少 CPU 内存占用。
  • 利用更多资源:使用表分区,可以增加并行操作,更大限度利用 CPU 资源。

总结到 SQL 优化中,就如下三点:

  • 最大化利用索引。
  • 尽可能避免全表扫描。
  • 减少无效数据的查询。

避免不走索引的场景
①尽量避免在字段开头模糊查询,会导致数据库引擎放弃索引进行全表扫描
②尽量避免使用 in 和 not in,会导致引擎走全表扫描
③尽量避免使用 or,会导致数据库引擎放弃索引进行全表扫描
④尽量避免进行 null 值的判断,会导致数据库引擎放弃索引进行全表扫描
⑤尽量避免在 where 条件中等号的左侧进行表达式、函数操作,会导致数据库引擎放弃索引进行全表扫描
⑥当数据量大时,避免使用 where 1=1 的条件
⑦查询条件不能用 <> 或者 !=
⑧where 条件仅包含复合索引非前置列
⑨隐式类型转换造成不使用索引
⑩order by 条件要与 where 中条件一致,否则 order by 不会利用索引进行排序
⑪正确使用 hint 优化语句

SELECT 语句其他优化
①避免出现 select *
②避免出现不确定结果的函数
③多表关联查询时,小表在前,大表在后
④使用表的别名
⑤用 where 字句替换 HAVING 字句
⑥调整 Where 字句中的连接顺序

增删改 DML 语句优化
①大批量插入数据
②适当使用 commit
适当使用 commit 可以释放事务占用的资源而减少消耗,commit 后能释放的资源如下:

  • 事务占用的 undo 数据块。
  • 事务在 redo log 中记录的数据块。
  • 释放事务施加的,减少锁争用影响性能。特别是在需要使用 delete 删除大量数据的时候,必须分解删除量并定期 commit。

③避免重复查询更新的数据
④查询优先还是更新(insert、update、delete)优先
MySQL 的默认的调度策略可用总结如下:

  • 写入操作优先于读取操作。
  • 对某张数据表的写入操作某一时刻只能发生一次,写入请求按照它们到达的次序来处理。
  • 对某张数据表的多个读取操作可以同时地进行。

MySQL 提供了几个语句调节符,允许你修改它的调度策略:

  • LOW_PRIORITY 关键字应用于 DELETE、INSERT、LOAD DATA、REPLACE 和 UPDATE。
  • HIGH_PRIORITY 关键字应用于 SELECT 和 INSERT 语句。
  • DELAYED 关键字应用于 INSERT 和 REPLACE 语句。

查询条件优化
①对于复杂的查询,可以使用中间临时表暂存数据
②优化 group by 语句
如果查询包括 GROUP BY 但你并不想对分组的值进行排序,你可以指定 ORDER BY NULL 禁止排序。
③优化 join 语句
连接(JOIN)..之所以更有效率一些,是因为 MySQL 不需要在内存中创建临时表来完成这个逻辑上的需要两个步骤的查询工作。
④优化 union 查询
原因在于如果没有 all 这个关键词,MySQL 会给临时表加上 distinct 选项,这会导致对整个临时表的数据做唯一性校验,这样做的消耗相当高。
⑤拆分复杂 SQL 为多个小 SQL,避免大事务

  • 简单的 SQL 容易使用到 MySQL 的 QUERY CACHE。
  • 减少锁表时间特别是使用 MyISAM 存储引擎的表。
  • 可以使用多核 CPU。

⑥使用 truncate 代替 delete

  • delete:删除全表时,会产生很大量的 binlog 并占用大量的 undo 数据块,此时既没有很好的效率也占用了大量的资源。
  • truncate:不会记录可恢复的信息,数据不能被恢复。也因此使用 truncate 操作有其极少的资源占用与极快的时间。另外,使用 truncate 可以回收表的水位,使自增字段值归零。

⑦使用合理的分页方式以提高分页效率

建表优化
①在表中建立索引,优先考虑 where、order by 使用到的字段。
②尽量使用数字型字段(如性别,男:1 女:2),若只含数值信息的字段尽量不要设计为字符型,这会降低查询和连接的性能,并会增加存储开销。
③查询数据量大的表 会造成查询缓慢。主要的原因是扫描行数过多。这个时候可以通过程序,分段分页进行查询,循环遍历,将结果合并处理进行展示。
④用 varchar/nvarchar 代替 char/nchar。
不要以为 NULL 不需要空间,比如:char(100) 型,在字段建立时,空间就固定了, 不管是否插入值(NULL 也包含在内),都是占用 100 个字符的空间的,如果是 varchar 这样的变长字段, null 不占用空间。


转自:https://mp.weixin.qq.com/s/qQCd1_MVfwQcn8q79QFIEw

 

“SELECT *”效率低

  • 增加查询分析器解析成本。
  • 增减字段容易与 resultMap 配置不一致。
  • 无用字段增加网络 消耗,尤其是 text 类型的字段。

①不需要的列会增加数据传输时间和网络开销

  • 用“SELECT * ”数据库需要解析更多的对象、字段、权限、属性等相关内容,在 SQL 语句复杂,硬解析较多的情况下,会对数据库造成沉重的负担。
  • 增大网络开销;* 有时会误带上如 log、IconMD5 之类的无用且大文本字段,数据传输 size 会几何增涨。如果 DB 和应用程序不在同一台机器,这种开销非常明显
  • 即使 MySQL 服务器和客户端是在同一台机器上,使用的协议还是 TCP,通信也是需要额外的时间

②对于无用的大字段,如 varchar、blob、text,会增加 IO 操作
准确来说,长度超过 728 字节的时候,会先把超出的数据序列化到另外一个地方,因此读取这条记录会增加一次 IO 操作。(MySQL InnoDB)

③失去 MySQL 优化器“覆盖索引”策略优化的可能性

索引知识延申
联合索引 (a,b,c)
联合索引 (a,b,c)实际建立了(a)、(a,b)、(a,b,c)三个索引

联合索引的优势
①减少开销
②覆盖索引
③效率高

索引是建的越多越好吗?答案自然是否定的:

  • 数据量小的表不需要建立索引,建立会增加额外的索引开销。
  • 不经常引用的列不要建立索引,因为不常用,即使建立了索引也没有多大意义。
  • 经常频繁更新的列不要建立索引,因为肯定会影响插入或更新的效率。
  • 数据重复且分布平均的字段,因此他建立索引就没有太大的效果(例如性别字段,只有男女,不适合建立索引)。
  • 数据变更需要维护索引,意味着索引越多维护成本越高。
  • 更多的索引也需要更多的存储空间。


转自:https://mp.weixin.qq.com/s/1ehicfKatMqNtkEDRHlfTg

 

MySql使用规范:

https://www.studytime.xin/article/mysql-internal-specifications.html

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值