Mysql Sub选择查询优化

时间:2010-01-18 16:24:09

标签: php sql mysql optimization subquery

我每天都在运行一个查询来编译统计信息 - 但它似乎效率很低。这是查询:

SELECT a.id, tstamp, label_id, (SELECT author_id FROM b WHERE b.tid = a.id ORDER BY b.tstamp DESC LIMIT 1) AS author_id
FROM a, b
WHERE (status = '2' OR status = '3') 
AND category != 6
AND a.id = b.tid
AND (b.type = 'C' OR b.type = 'R')
AND a.tstamp1 BETWEEN {$timestamp_start} AND {$timestamp_end}
ORDER BY b.tstamp DESC
LIMIT 500

这个查询似乎运行得很慢。为废话命名道歉 - 我被要求不透露实际的表名。

存在子选择的原因是因为外部选择从表a获得一行并且它从表b获得一行。但是也需要从表b中知道最新的author_id,所以我运行一个子选择来返回那个。我不想在php循环中运行另一个select - 因为这也是低效的。

它工作正常 - 我只需要找到一种更快的方法来获取这个数据集。

2 个答案:

答案 0 :(得分:2)

尝试:

  SELECT a.id,
         b.tstamp,
         label_id,
         y.author_id
    FROM TABLE_A a
    JOIN TABLE_B b ON b.tid = a.id
    JOIN (SELECT b.tid,
                 MAX(b.tstamp) 'm_tstamp'
            FROM TABLE_B b
        GROUP BY b.tid) x ON x.tid = a.id
    JOIN (SELECT b.tid,
                 b.author_id,
                 b.tstamp
            FROM TABLE_B b
        GROUP BY b.tid) y ON y.tid = a.id
                         AND y.tstamp = x.m_tstamp
   WHERE status IN ('2', '3')
     AND b.type IN ('C', 'R')
     AND category != 6
     AND a.tstamp1 BETWEEN {$timestamp_start} AND {$timestamp_end}
ORDER BY b.tstamp DESC 
   LIMIT 500

答案 1 :(得分:2)

如果b.tstamp中的b.tid是唯一的,请参阅OMG Ponies的解决方案。

否则你可以尝试这个解决方案。它按b.tstamp DESC对整个结果进行排序,并按author_id添加排名。外部选择仅使用rank = 1的行,该行是tstampauthor_id个{。}}。

SELECT id, tstamp, label_id, author_id
  FROM (SELECT id,
               tstamp,
               label_id,
               author_id,
               CASE
                 WHEN @author_id != author_id THEN @row_num := 1 
                 ELSE @row_num := @row_num + 1
               END AS rank,
               @author_id := b.author_id
          FROM a,
               b,
               (SELECT @row_num := 0, @author_id := NULL) y
          WHERE a.id = b.tid
          AND (status = '2' OR status = '3') 
          AND category != 6
          AND (b.type = 'C' OR b.type = 'R')
          AND a.tstamp1 BETWEEN {$timestamp_start} AND {$timestamp_end}
          ORDER BY b.author_id, b.tstamp DESC
  ) x
 WHERE x.rank = 1
LIMIT 500

我还没有尝试过,所以如果它不起作用请发表评论。