面试时经常会被问到数据库优化的问题。今天给大家总结几点:SQL和索引的第一阶段优化。这是调整的第一阶段。为什么?因为这一步的成本很便宜,所以不需要添加任何中间件。步骤是什么?先说利用慢查询日志定位执行效率低的SQL语句。使用explain对SQL执行计划进行分析,确定问题所在,并采取相应的优化措施,比如建立索引。第二阶段是使用缓存来优化SQL。问题解决后,再考虑建缓存。毕竟你缓存的目的是缓存复杂的、耗时的、不经常变化的执行结果,以减少数据库的资源消耗。这里需要注意的是,缓存构建完成后,系统的复杂度会增加。你需要考虑很多问题,比如:缓存和数据库一致性问题?(比如更新缓存还是删除缓存)如何解决缓存击穿、缓存穿透、缓存雪崩等问题?是否有必要做缓存预热。但我估计,大多数中小企业应该不会考虑。第三阶段,当读写分离缓存还不确定时,进行主从复制,进行读写分离。在应用层,区分读写请求。或者使用现成的中间件mycat或者altas来实现读写分离。需要注意的是,只要你敢说自己用的是主从架构,就需要准备三个问题:1、主从的好处?答:实现数据库备份,实现数据库负载均衡,提高数据库可用性2、主从原理?答:如图,主库有一个logdump线程,将binlog传递给从库。从库有两个线程,一个I/O线程,一个SQL线程,I/O线程读取主库传来的binlog内容并写入relaylog,SQL线程从relaylog中读取内容并写入从库的数据库中。3、如何解决主从一致性问题?答:我不建议在数据库级别解决这个问题。根据CAP定理,主从架构本来就是高可用架构,无法满足一致性。即使你使用同步复制模式或者半同步复制模式,也是弱一致性,而不是强一致性。所以建议使用缓存来解决这个问题。步骤如下:自己测试通过,计算主从延迟时间。建议mysql版本为5.7以上,因为mysql从5.7开始多线程复制功能比较完善,一般可以保证延迟在1s以内。不过话说回来,mysql现在出到8.x了,还有人用5.x版本吗?对于数据库的写操作,先写数据库,再写缓存,但是有效期很短,比主从延迟时间略长。读取请求时,先读取缓存,缓存存在则直接返回。如果缓存不存在(此时主从同步已经完成),重新读取数据库。第四阶段使用分区表说实话,面试的时候其实可以跳过这个阶段。因为很多互联网公司不推荐使用分区表,我自己也不推荐使用分区表。使用这个分区表有太多的陷阱。下面是对其他文章的一些回答:什么是mysql分区表?答:所有的数据还是在一张表中,只是物理存储按照一定的规则放在了不同的文件中。这是mysql支持的功能。业务代码不用改,但是sql语句需要改,sql条件需要带分区列。缺点:分区键的设计不是很灵活。如果不使用partitionkey,很容易锁住整张表。在分区表上使用ALTERTABLE...ORDERBY时,只能在每个分区内执行orderby。如果在分区表的分区键上创建索引,那么这个索引也会被分区。没有分区键的全局索引这样的东西。自己分离数据库和表,自己控制业务场景和访问方式,是可控的。对于分区表,我写了一个sql用于研发,但是不确定要查哪个分区,不可控。第五阶段垂直分裂以上四个阶段都没有完成,所以垂直分裂来了。垂直拆分的复杂度仍然小于水平拆分的复杂度。按模块将您的表拆分为不同的小表。《大型网站架构演变之路》大家应该都看过了,这类文章或书籍基本都提到了这个阶段。如果你有幸在运营商、银行等公司工作,你会发现他们有一张表有几百个字段是很常见的。因此,应该进行拆分。拆分的原则一般是以下三点:将不常用的字段放在一个单独的表中。将常用的字段放在单独的表中,将经常组合查询的列放在一张表中(联合索引)。第六阶段水平分裂水平分裂是最麻烦的阶段。拆分后会出现很多问题。再次强调,水平拆分一定是最好的选择。从某种意义上说,我认为垂直拆分更好。因为你用垂直拆分,分成不同的模块后,你发现单个模块的压力太大了。你完全可以单独优化这个模块,比如提升这个模块的机器配置。如果是横向拆分,拆分成两张表,需要改代码,然后发现两张表不行,再改代码,再拆分成三张表?水平拆分后,模块之间的耦合太强,成本太高,要慎重。
