繁体   English   中英

在真实数据库上的JOIN查询速度太慢,在小型数据库上运行正常

[英]JOIN query too slow on real database, on small one it runs fine

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

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

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

这是东西:

我有表: users_bonitet 该表具有以下字段: iduser_idbonitettstamp

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

users_bonitet表中的三个关键字段是: user_id (引用user.id ), bonitet (代表用户的强度,它可以具有3个值, 1-2-3 ,其中3是最佳值)和tstamp(存储时间)每次当某些用户更改了bonitet值时,都会插入新行,并附带该插入的tstamp以及新的bonitet值。) 因此,基本上,一些用户可以将1的bonitet表示自己处于不良状况,但一段时间后可以将其更改为3,表示他的工作状况很好,并且该更改的时间存储在tstamp中

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

一些用户(公司)是俱乐部的成员。 俱乐部成员可以提供一些俱乐部要约(他向人们和其他俱乐部成员展示自己的产品),并且在某些地区运营。

我需要做的是为每个俱乐部要约(由某个俱乐部成员的用户提供)获得最优惠的价格,但仅针对ID为1100000的特定区域; 由于每位用户的参数值都会随着时间而变化,这意味着我只需要获取最新的值。 因此,如果某位用户在2012年1月21日的第一位参数为bonitet,但在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

因此,我正在为ID为1100000的俱乐部会员的用户提供的所有俱乐部要约选择原始值。重要的是,我正在选择club_offer.id AS offerId,因为我需要在其中使用该offerId我的应用程序代码,这样我就可以基于为每个要约返回的原始值进行一些计算,并为要约ID为id的每一行插入计算到的字段“ club_offer.rank”。

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

子查询是:

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

如果将(user_id, tstamp)添加为该表的索引,则非常高效的松散索引扫描可以满足该子查询。

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

请注意,如果此users_botinet表中具有自动递增的ID号,则可以将您的子查询重构为使用该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/

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM