php - JOIN 查询在真实数据库上太慢,在小型数据库上运行良好

标签 php mysql database performance join

我需要有关执行时间过长或根本不执行的 mysql 查询的帮助。

(我正在尝试做的是更复杂问题的一部分,我想创建 PHP cron 脚本,它将执行一些繁重的查询并根据返回的结果计算数据,然后使用这些数据将其存储在数据库中以供使用更方便的使用。很可能我会在这里对这个过程提出疑问。)

首先让我们尝试解决这些繁重查询的问题之一。

事情是这样的:

我有表:users_bonitet。此表包含字段:iduser_idbonitettstamp

首先要注意:当我说用户时,请理解用户实际上是公司,而不是人。所以 user.id 是某个公司的 ID,但由于某些其他原因,我在这里使用的表称为“users”。

users_bonitet表中的三个关键字段是:user_id(引用user.id),bonitet(代表用户的强度,它可以有 3 个值,1 - 2 - 3,其中 3 是最好的)和 tstamp(存储 bonitet 插入的时间。每次当某些用户的 bonitet 值发生变化时,新行插入 tstamp该插入物,当然还有新的 bonitet 值。)。所以基本上有些用户可以将 bonitet 设置为 1,表示他处境不佳,但一段时间后它可以变为 3,表示他做得很好,并且该更改的时间存储在 tstamp 中。

现在,我将仅列出我们需要在查询中使用的其他表,然后我将解释原因。表是:userclubclub_offerclub_territories

一些用户(公司)是俱乐部的成员。俱乐部成员可以获得一些俱乐部优惠(他向人们和其他俱乐部成员代表他的产品)并且他在一些领土上经营。

我需要做的是为每个俱乐部报价(由某个俱乐部成员(member)的用户提供)获取 bonitet 值(value),但仅限于 ID 为 1100000 的特定区域;由于每个用户的 bonitet 值都在随时间变化,这意味着我只需要获取最新的值。因此,如果某些用户在 2012 年 1 月 21 日的 bonitet 为 1,但后来在 2012 年 5 月 26 日更改为 2,我只需要获取 2,因为这是当前值。

我用我现在正在使用的示例数据库模式和查询制作了一个 SQL Fiddle。在这个小数据库上,查询正在按我的要求工作,而且速度很快,但在真实数据库上它非常慢,有时根本不执行。

在这里查看:http://sqlfiddle.com/#!9/b0d98/2

我的问题是:我是否使用了错误的查询来获取所有这些数据?我得到了正确的结果,但也许我的查询不好,这就是它执行如此缓慢的原因?我怎样才能加快速度?我尝试过使用 phpmyadmin 放置索引,但没有太大帮助。

这是我的查询:

SELECT users_bonitet.user_id, users_bonitet.bonitet, users_bonitet.tstamp,
       club_offer.id AS offerId, club_offer.rank

FROM users_bonitet

INNER JOIN (
     SELECT max( tstamp ) AS lastDate, user_id
     FROM users_bonitet
     GROUP BY user_id
)lastDate ON users_bonitet.tstamp = lastDate.lastDate

AND users_bonitet.user_id = lastDate.user_id

JOIN users ON users_bonitet.user_id = users.id
JOIN club ON users.id = club.user_id
JOIN club_offer ON club.id = club_offer.club_id
JOIN club_territories ON club.id = club_territories.club_id

WHERE club_territories.territory_id = 1100000

因此,我为所有俱乐部成员(member)提供的所有俱乐部报价选择 bonitet 值,这些俱乐部成员(member)在 id 为 1100000 的领土上运营。重要的是我选择 club_offer.id AS offerId,因为我需要使用在我的应用程序代码中添加那个 offerId,这样我就可以根据为每个优惠返回的 bonitet 值进行一些计算,并将计算的数据插入到字段“club_offer.rank”中,用于 ID 为 offerId 的每一行。

最佳答案

您的查询看起来不错。我怀疑如果您添加一个复合索引来帮助子查询从 users_botinet 中为每个用户找到最新条目,您的查询性能可能会得到改善。

子查询是:

   SELECT max( tstamp ) AS lastDate, user_id
     FROM users_bonitet
    GROUP BY user_id

如果您将(user_id, tstamp) 添加为该表的索引,则可以使用非常高效的loose index scan 来满足该子查询。 .

ALTER TABLE users_bonitet ADD KEY maxfinder (user_id, tstamp);

请注意,如果此 users_botinet 表中有一个自动递增的 ID 号,您的子查询可以重构为使用它而不是 tstamp。这将消除重复的可能性并且效率更高,因为有一个唯一的 id 用于加入。就像这样。

  FROM users_botinet
  INNER JOIN (
         SELECT MAX(id) AS id
           FROM users_botinet
          GROUP BY user_id
       ) ubmax ON users_botinet.id = ubmax.id

在这种情况下,您的复合索引将是 (user_id, id

专业提示:不要添加大量索引,除非您知道自己需要它们。阅读索引如何帮助您是个好主意。例如。 http://use-the-index-luke.com/

关于php - JOIN 查询在真实数据库上太慢,在小型数据库上运行良好,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29121265/

相关文章:

PHP析构函数行为问题

php - 如何联合所有+1表?

使用多个查询发送邮件的 PHP (PDO) 文件

sql - 弃用数据库模式中的列的最佳方法是什么?

c++ - 使用基于签名的技术编写防病毒软件

database - 城市到大都市区

php - SQL 注入(inject)、real_escape_string 和引用查询

php - 如何按类别列出评论? (操作数组)

php - 使用 for 循环更新表图像

mysql - 在 XAMPP 上同步/复制 MySQL 数据库,大部分时间离线笔记本电脑和在线台式机