PHP与MySQL的性能 - 一个大的查询与多个小

PHP与MySQL的性能 - 一个大的查询与多个小

问题描述:

对于我使用InnoDB引擎和我的表结构的MySQL表看起来是这样的:PHP与MySQL的性能 - 一个大的查询与多个小

表用户

id | username | etc... 
----|------------|-------- 
    1 | bruce  | ... 
    2 | clark  | ... 
    3 | tony  | ... 

表用户的电子邮件

id | person_id | email 
----|-------------|--------- 
    1 |   1 | [email protected] 
    2 |   1 | [email protected] 
    3 |   2 | [email protected] 

为了从数据库中提取数据我已经写了一个小framewor ķ。例如。在__construct($id)它检查是否有一个人与给定的ID,如果是,它会创建相应的模型,并只保存字段id到一个数组。在运行期间,如果我需要模型中的另一个字段,它只会从数据库中提取值,并将其保存到数组中并将其返回。例如。与emails相同,因为我的代码访问表user-emails并获取相应用户的所有电子邮件。

对于小型模型来说,这个工作正常,但现在我正在处理另一个项目,我必须一次为列表获取大量数据,并且需要一些时间。另外我知道很多连接到MySQL和许多查询对服务器来说都是很有压力的,所以...

我现在的问题是:我应该在构建模型时一次获取所有数据(包含左连接等)并将这些字段保存为一个数组,或者我应该使用其他方法?

+0

...取决于。一般来说,使用许多简单的查询将比使用一个复杂的查询更好;但这取决于它的复杂程度以及您的索引是如何设置的。 – CD001

+0

您应该只测量性能并查看是否有问题。 – pvg

+0

@ CD001这个评论实际上让我感到惊讶,人们试图将许多SQL查询填充到一个大查询中的数量使我认为更少的大型查询通常说起来效率更高.....我想我不应该跟随人群。 ....':-D' – Martin

为什么人们坚持将实体和领域对象称为“模型”。

除非您的实体非常大,否则我会在您需要时填充整个实体。而且,如果“电子邮件清单”是该实体的一部分,我也会填写该清单。

正如我所看到的,问题更多地与“如何处理与外键相关的表”有关。

可以假设你有UsersArticles表,其中每篇文章有一个特定的所有者通过user_id外键关联。在这种情况下,当填充Article实体时,我只会检索user_id值,而不是提取有关用户的所有信息。

但与UsersUserEmails您例如,电子邮件似乎是User实体的一部分,和东西,你会经常通过$user->getEmailList()调用。

TL; DR

填充User实体时,我会在两个查询,这样做:

  1. 选择你从用户表需要,适用于User实体
  2. 选择所有用户来自UserEmails表的电子邮件并将其应用于User实体。

P.S

你可能想看看data mapper模式的“how”部分。

+0

'users' +'articles'的例子有些不同,那些基本上是2个不同的实体。在我的情况下,所有其他表都属于同一个实体,现在我所有的都出现在列表中。 – donnikitos

+0

您是否阅读过以“但在您的例子中......”开头的部分? –

+0

是的,刚才要考虑这个解决方案。那么PHP呢?如果我不使用主表的某些区域,那么这不会污染内存吗? – donnikitos

在我看来,你应该一次获取所有的字段,并以一种让你的代码更容易阅读/管理的方式划分查询。

当我们谈论一个或两个查询时,除非组合查询(与JOIN s或其他)过于复杂,否则通常可以忽略不同。通常,一个或两个索引是解决非常慢的查询问题的方法。

如果我们谈论的是一个vs数百或数千个查询,那么连接/传输开销变得更加重要,并且减少查询次数可以产生影响。

看来你的框架遭受premature optimization。你太担心从行中取得太多的字段,但为什么?你有成千上万的专栏吗?

查询耗时的部分几乎总是查找,而不是数据的传输。当您一次拉一个字段时,您正在导致数据库一遍又一遍地执行“硬”部分。

+0

我只是想知道这将如何影响服务器。当然,我不会有成千上万的列,但是在70左右。如果我一次加载100行,总共将有7000个字段,这就是我想到的。 – donnikitos

+1

我会更关心7000个查询以获得100行数据,而1个查询则获得7000个字段。即使每个字段都是20个字节,我们仍然只谈论140 KB的数据。 – jchook

+0

再说一遍,你说10秒钟就可以加载60行。这太疯狂了。 MySQL可以查询60行,并在眨眼间连接11个表(每行有数百行和25列)。 – jchook