哪个更快,一个大查询还是多个小查询?

sud*_*.ie 93 mysql postgresql performance join query-performance

我一直在为不同的公司工作,我注意到他们中的一些人更喜欢拥有将所有“亲戚”加入表格的视图。但是在应用程序中,有时我们只需要使用 1 列。

那么只进行简单的选择,然后将它们“加入”到系统代码中会更快吗?

该系统可以是 php、java、asp 或任何连接到数据库的语言。

所以问题是,从服务器端(php、java、asp、ruby、python...)到数据库并运行一个查询来获取我们需要的一切或从服务器端到数据库并运行哪个更快?一次只从一个表中获取列的查询?

Rol*_*DBA 88

什么可以解决您的问题是主题 JOIN DECOMPOSITION。

根据本书第 209 页

高性能 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';
Run Code Online (Sandbox Code Playgroud)

您可以运行以下查询:

SELECT * FROM tag WHERE tag = 'mysql';
SELECT * FROM tag_post WHERE tag_id=1234;
SELECT * FROM post WHERE post.id IN (123,456,567,9098,8904);
Run Code Online (Sandbox Code Playgroud)

你到底为什么要这样做?乍一看,这看起来很浪费,因为您增加了查询次数而没有得到任何回报。但是,这种重组实际上可以带来显着的性能优势:

  • 缓存可以更有效。许多应用程序缓存直接映射到表的“对象”。在这个例子中,如果带有标记的对象mysql已经被缓存,应用程序将跳过第一个查询。如果您在缓存中发现 ID 为 123、567 或 908 的帖子,您可以将它们从IN()列表中删除。查询缓存也可能受益于这种策略。如果只有一个表频繁更改,分解连接可以减少缓存失效的次数。
  • 单独执行查询有时可以减少锁争用
  • 在应用程序中进行连接可以通过将表放置在不同的服务器上来更轻松地扩展数据库。
  • 查询本身可以更有效。在这个例子中,使用IN()列表而不是连接可以让 MySQL 对行 ID 进行排序,并比使用连接可能更优化地检索行。
  • 您可以减少冗余行访问。在应用程序中进行连接意味着只检索每一行一次,而查询中的连接本质上是一种非规范化,可能会重复访问相同的数据。出于同样的原因,这种重组也可能会减少总网络流量和内存使用量。
  • 在某种程度上,您可以将此技术视为手动实现散列连接,而不是 MySQL 用来执行连接的嵌套循环算法。散列连接可能更有效。

因此,当您缓存和重用来自早期查询的大量数据、将数据分布到多个服务器、用IN()列表替换连接或连接多次引用同一个表时,应用程序中的 dos 连接可以更有效。

观察

我喜欢第一个要点,因为 InnoDB 在交叉检查查询缓存时有点笨手笨脚。

至于最后一个要点,我在 2013 年 3 月 11 日写了一篇文章(JOIN 条件和 WHERE 条件之间是否有执行差异?),描述了嵌套循环算法。阅读之后,您将看到连接分解可能有多好。

至于本书中的所有其他观点,开发人员确实将性能作为底线。有些依赖外部手段(应用程序之外)来增强性能,例如使用快速磁盘、获得更多 CPU/内核、调整存储引擎和调整配置文件。其他人会屈服并编写更好的代码。有些人可能会在存储过程中对所有商业智能进行编码,但仍然没有应用连接分解(请参阅反对或支持将应用程序逻辑放入数据库层的论据是什么?以及其他帖子)。这完全取决于每个开发商商店的文化和容忍度。

有些人可能对性能感到满意,不再接触代码。其他人根本没有意识到如果他们尝试加入组合,可以获得很大的好处。

对于那些愿意...

试一试 !!!

  • 至于那个关于更改为 3 个查询的链接......我知道并尊重 Baron、Vadim 和 Peter,但我不同意这个误导性的建议。大多数支持拆分的论点都非常罕见,不值一提。坚持使用 JOIN 进行单个查询,然后让我们改进它。 (6认同)
  • @RickJames 我同意你评论的精神。多年来,我看到一些人加入分解工作,而另一些人则失败了。即使使用适当的 SQL 技能集,如果连接分解没有正确完成,它也可能对您不利。在我现在的雇主,许多部门喜欢扩大规模,尤其是在涉及遗留代码并且资金雄厚的情况下。对于那些有鱼子酱口味但鸡蛋沙拉预算有限的人来说,加入分解可能值得冒险,但必须正确完成。 (2认同)

Erw*_*ter 39

Postgres的(也可能任何RDBMS程度相近,MySQL的程度较轻),较少的查询几乎都是快。

在大多数情况下,解析和规划多个查询的开销已经超过了任何可能的收益。

更不用说在客户端完成额外的工作,结合结果,这通常慢得多。RDBMS 专门从事这种任务,操作基于原始数据类型。无需text为中间结果进行转换或返回转换或转换为客户端的本机类型,这甚至可能导致不太正确(或不正确!)的结果。想想浮点数...

您还可以在数据库服务器和客户端之间传输更多数据。这对于一手充满价值的手来说可能可以忽略不计,或者产生巨大的差异。

如果多次查询意味着多次往返数据库服务器,您还需要多次收集网络延迟和事务开销,甚至可能是连接开销。大,大损失。

根据您的设置,单独的网络延迟可能比其他所有延迟要长几个数量级。

关于SO的相关问题:

对于非常大的、长时间运行的查询,可能会有一个转折点,因为事务会在途中收集 DB 行上的锁。非常大的查询可能会在很长一段时间内持有许多锁,这可能会导致并发查询的摩擦。

  • 通过外连接,RDBMS 从父表中返回为每个连接的子表复制的数据,这意味着一些网络和内存开销,然后在 ORM 工具中进行一些额外的解析,以丢弃重复的父值并仅保留一个父表和 n 个子表。因此,通过单个查询,我们可以节省 RDBMS 查询规划器的高效工作、减少网络(或本地管道)请求,但会损失额外不需要的负载以及在 ORM 库中移动数据。我想,一如既往——优化之前先测量。 (2认同)

归档时间:

查看次数:

132146 次

最近记录:

5 年,4 月 前