背景
经历了一段漫长痛苦的重构期,整体的业务重构基本完成。这里总结下重构中遇到的一些问题和经验。这里主要讲下分解关联查询。
例子
例如一个查询标签为‘mysql’的所有文章的关联查询sql:1
2
3
4select * from tag
join tag_post on tag_post.tag_id = tag.id
join post on tag_post.post_id = post.id
where tag.tag = 'mysql';
分解成以下多个sql,在应用层做关联:1
2
3select id from tag where tag = 'mysql';
select * from tag_post where tag_id=1234;
select * from post where post.id in (123,456,...);
分解关联查询的优点
缓存的效率更高
应用程序可以很方便的缓存单表查询的结果。例如例子中分解后的第1个查询,如果已经在缓存中,这可以跳过第1个查询。
另外对于mysql的query cacha(查询缓存)来说,如果关联查询中的任意表发生了变化,就无法使用缓存,而拆分后,如果其中一个表很少改变,那么该表的缓存命中将很高。
减少数据库锁竞争
查询分解后,执行单个查询可以减少锁的竞争,而关联查询将可能锁多个表。
微服务化友好
应用层做关联,可以更容易的做数据库拆分,更容易做到高性能和可扩展。对于原本的单体应用做微服务化拆分与改造将非常便捷。
查询效率提升
例如例子中的第3个查询,使用了in()代替了关联查询,可以让mysql按照id顺序进行查询,这比随机的关联要更高效。
减少冗余记录的查询
在应用层做关联,意味着对某条记录只需查询一次,而在数据库关联查询,则可能需要重复地访问一部分数据。从这点看,这样还能减少网络和内测消耗。
关联更高效
在应用层关联,往往比mysql中的嵌套循环关联更高效。