1

首先,我很抱歉,因为我无法为这个问题想出更好的标题。

我的网站上有一个徽章/成就系统,社区用户根据他们在网站上的活动获得特定的徽章奖励,下面的 sql 示例我用来提取至少发表 100 个论坛帖子的用户数量(我使用的是 informix db版本 10)

SELECT tjm.userid::INTEGER AS user_id, 
  EXTEND(DBINFO("UTC_TO_DATETIME",tjm.creationdate/1000), year to fraction) 
    AS earned_date
FROM TABLE(
  MULTISET(
    SELECT jm.userid, jm.creationdate, (
      SELECT COUNT(*) from TABLE(
        MULTISET(
          SELECT userid, creationdate
          FROM jive:jivemessage
        )
      ) AS i 
      WHERE i.userid = jm.userid AND i.creationdate < jm.creationdate
    ) + 1 AS row_num
    FROM jive:jivemessage jm 
  )
) AS tjm 
WHERE tjm.row_num=100

这条 sql 执行大约需要 30 多分钟,我们有一个非常大的社区,并且有数百万个论坛帖子。

我想知道是否有提高查询性能的解决方案?我试图减少执行时间,因为我有 40 个与此类似的 sql 查询,但针对不同的表和活动。

4

1 回答 1

1

我现在不使用 Informix DB,但下面的查询应该按照您的要求进行,它是 ANSI SQL(除了 EXTEND 部分,我从您的原始查询中复制了它)。

SELECT
  jm.userid
  ,EXTEND(DBINFO("UTC_TO_DATETIME",tjm.creationdate/1000), year to fraction) AS earned_date
FROM
  (
  -- This sub-query will return all Users who have 100 messages or more
  SELECT
    jm.userid
    ,count(jm.userid) as totalmessages
  FROM
    jive:jivemessage jm
  GROUP BY
    jm.userid
  HAVING
    count(jm.userid) >= 100) AS MessageCount

以上可能无需使用子查询即可完成。我使用它的唯一原因是根据原始查询在结果集中拥有 DateEarned。将它添加到子查询将需要将其添加到 GROUP BY,如果查询运行两天(例如,在 23:59:59),则会产生不可预测的结果。

更新 2012/08/14 - 根据新要求重写查询

正如我之前所说,我根本不了解 Informix,因此以下查询可能会运行,也可能不会运行。

SELECT
  UsersWithBadge.userid
  ,MAX(UsersWithBadge.creationdate) as dateearned
FROM
  (
  SELECT FIRST 100
    jm.userid
    ,jm.creationdate
  FROM
    jive:jivemessage jm
    JOIN
    (-- This sub-query will return all Users who have 100 messages or more
    SELECT
      jm.userid
      ,count(jm.userid) as totalmessages
    FROM
      jive:jivemessage jm
    GROUP BY
      jm.userid
    HAVING
      count(jm.userid) >= 100)
    AS MessageCount ON
      (MessageCount.userid = jm.userid)
  ) AS UsersWithBadge     
GROUP BY
  UsersWithBadge.userid
于 2012-08-14T16:26:46.603 回答