MySql数据库单表查询与多表连接查询效率对比
作者:不会编程的派大星 发布时间:2024-01-26 12:28:05
这段时间在做项目的过程中,遇到一个模块,数据之间的联系很复杂,在建表的时候就很纠结,到底该怎么去处理这些复杂的数据呢,是单表查询,然后在业务层去处理数据间的关系,还是直接通过多表连接查询来处理数据关系呢?
通过查阅资料和阅读博客,有以下两个回答:
一、《高性能mysql》中的回答
很多高性能的应用都会对关联查询进行分解。简单地,可以对每个表进行一次单表查询,然后将结果在应用程序中进行关联。例如,下面这个查询:
select * 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';
可以分解成下面这些查询来代替:
Select * from tag where tag='mysql';
Select * from tag_post where tag_id=1234;
Select * from post where id in(123,456,567,9989,8909);
到底为什么要这样做?
咋一看,这样做并没有什么好处,原本一条查询,这里却变成了多条查询,返回结果又是一模一样。
事实上,用分解关联查询的方式重构查询具有如下优势:(高并发、高性能的应用中,一般建议使用单表查询)
1. 让缓存的效率更高。许多应用程序可以方便地缓存单表查询对应的结果对象。另外对于MySQL的查询缓存来说,如果关联中的某个表发生了变化,那么就无法使用查询缓存了,而拆分后,如果某个表很少改变,那么基于该表的查询就可以重复利用查询缓存结果了。
2. 将查询分解后,执行单个查询可以减少锁的竞争。
3. 在应用层做关联,可以更容易对数据库进行拆分,更容易做到高性能和可扩展。
4. 查询本身效率也可能会有所提升。
5. 可以减少冗余记录的查询。
6. 更进一步,这样做相当于在应用中实现了哈希关联,而不是使用MySQL的嵌套环关联,某些场景哈希关联的效率更高很多。
7. 单表查询有利于后期数据量大了分库分表,如果联合查询的话,一旦分库,原来的sql都需要改动。
8. 上次看到某个CTO技术分享,公司规定底层禁止用join联合查询。数据大的时候确实慢。
9. 联合查询或许确实快,但是mysql的资源通常比程序代码的资源紧张的多。
二、其他的一些回答
情景假设:假设网站有一个公司库版块,我想搜索某城市的所有公司。
数据表:tbl_company (t1)、 tbl_city (t2)。
例1:
t1表中存cityid 根据id做表连接查询
select * from t1 inner join t2 on t1.cityid=t2.cityid;
例2:
t1表中存cityName 用户前台点击上海市,则把上海市的id传到后台(不考虑传cityName),
根据id查出cityName select cityName from t2 where cityid= #{cityid};
然后 select * from t1 where cityName = #{cityName};
两者区别:例1中只做了一次表关联查询,例2中分别做了两次单表查询。
考虑到数据量大,多表连接查询会影响查询效率所以都优化为单表查询。 TP:以上是在不使用索引的情况下
请问哪种效率会更高些?
答:sql优化与业务也有关系,这条语句的查询会不会频繁,要不要考虑2次连接带来的开销,如果这些都不用考虑的话,都没有索引的情况下,感觉相差不大,2应该略优于1。
数据没有特别大的情况还是级联查询快。
对于传统的数据库涉及来说, 尽可能减少数据库查询次数.
BUT, 1. mysql都对处理连接/断开连接, 回复小而简单的 查询是非常快的; 2.现在的网络已经非常快了. 所以多个小的查询对mysql来说可能更快一些.
最后, 大神也没有结论哪个更好. 呵呵, 其实整本书都明确表达一个意思, 测试测试! 做benchmark! 对于自己的数据环境, 把两种方式都测试一下. 用数据说话.
三、总结
个人建议还是用单表查询!在应用层做数据之间的关联会更好!
来源:https://blog.csdn.net/weixin_45827693/article/details/118094163


猜你喜欢
- 下面两个函数的使用和FIND_IN_SET一样,使用时只需要把FIND_IN_SET换成FIND_PART_IN_SET或FIND_ALL_
- date("yyyyMMdd",time()) date() 函数功能:用于格式化时间,返回一个字符串。&nb
- 我就废话不多说了,直接上代码吧!#coding=utf-8'''openCV中最核心的的类是Mat,他是matrix
- 1.预构建网络class Net(nn.Module): def __init__(self): su
- 一、创建虚拟环境(1)打开cmd命令窗口(2)创建虚拟环境 conda create -n mydjango_env(3)查看虚拟环境 co
- 一、Pytest概念Pytest 是 Python 的一种单元测试框架,与 Python 自带的 unittest 测试框架类似,但是比 u
- 1. v-model 表单输入绑定使用v-model创建双向数据绑定, 用来监听用户的输入事件以更新数据,并对一些极端场景进行一些特殊处理。
- python的新式类是2.2版本引进来的,我们可以将之前的类叫做经典类或者旧式类。为什么要在2.2中引进new style class呢?官
- 你家中的CD、VCD一定很多吧?是不是常遇到为找一张CD把一抽屉的碟子翻得乱七八糟的情况,你一定没少受埋怨——你不想整理它们一下?如:影片是
- 本文实例讲述了python实现linux下使用xcopy的方法。分享给大家供大家参考。具体如下:这个python函数模仿windows下的x
- 前言:协程(coroutine)是 Go 语言最大的特色之一,goroutine 的实现其实是通过协程。协程的概念协程一词最早出现在 196
- 这次介绍日期数据处理。用python中的方法对日期数据进行处理, 我们可以获取很多有用的信息, 比如年月日,星期,周次,季度等, 这里分享工
- javascript编写的窗口代码,可以关闭显示窗口,可以最小化或还原窗口大小,还可以鼠标移动窗口,不错的一个功能。截图如下:<htm
- Oracle数据库在使用的过程中常常会遇到这样或那样的问题,而这些问题常常又使我们感到很困惑,本文我们总结了Oracle数据库在使用过程中的
- 最近要做数据库同步,如果网上找了例子,成功,记录下来,下回再看。这个是网上找的一编文章。以下配置在本机上已经成功:实现功能:A为主服务器,B
- 基于selenium进行动作链由于最近很多人聊到滑动验证码怎么处理,所以决定自己动手试一下。做一个东西前。我们首先要对这个东西的操作过程有一
- --建递增序列CREATE SEQUENCE LZEAM_SP_LOOP_EQ_SEQ MINVALUE 1 INCREMENT BY 1
- 本文实例讲述了Python数据结构与算法之图的最短路径(Dijkstra算法)。分享给大家供大家参考,具体如下:# coding:utf-8
- 一、备份数据库1、打开SQL企业管理器,在控制台根目录中依次点开Microsoft SQL Server2、SQL Server组-->
- Tensorboard:如何更直观的观察数据在神经网络中的变化,或是已经构建的神经网络的结构。上一篇文章说到,可以使用matplotlib第