MySQL依赖的子查询何时应该是独立的

时间:2011-02-03 10:48:42

标签: mysql optimization

当我解释这个问题时:

SELECT DISTINCT(u.mail)
FROM ep_point_transactions pt
  JOIN ep_transaction_status ts ON ts.tid = pt.tid
  JOIN users u ON u.uid = pt.uid
WHERE ts.anulada IS NULL
  AND pt.anulada IS NULL
  AND ts.source = 'rake'
  AND (pt.educapuntos * pt.multiplicador) >= 7500
  AND ts.timestamp < '2010-11-30 23:00:00'
  AND pt.uid NOT IN (
    SELECT distinct(pt2.uid)
    FROM ep_point_transactions pt2
      JOIN ep_transaction_status ts2 ON ts2.tid = pt2.tid
    WHERE ts2.anulada IS NULL
      AND pt2.anulada IS NULL
      AND ts2.source = 'rake'
      AND ts2.timestamp > '2010-11-30 23:00:00'
  );

我正在获得此输出:

+----+--------------------+-------+--------+----------------+---------+---------+-------------------------+------+------------------------------+
| id | select_type        | table | type   | possible_keys  | key     | key_len | ref                     | rows | Extra                        |
+----+--------------------+-------+--------+----------------+---------+---------+-------------------------+------+------------------------------+
|  1 | PRIMARY            | ts    | ref    | PRIMARY,source | source  | 194     | const                   | 2997 | Using where; Using temporary |
|  1 | PRIMARY            | pt    | ref    | PRIMARY        | PRIMARY | 4       | educapoker.ts.tid       |   30 | Using where                  |
|  1 | PRIMARY            | u     | eq_ref | PRIMARY        | PRIMARY | 4       | educapoker.pt.uid       |    1 |                              |
|  2 | DEPENDENT SUBQUERY | ts2   | ref    | PRIMARY,source | source  | 194     | const                   | 2997 | Using where; Using temporary |
|  2 | DEPENDENT SUBQUERY | pt2   | eq_ref | PRIMARY        | PRIMARY | 8       | educapoker.ts2.tid,func |    1 | Using where                  |
+----+--------------------+-------+--------+----------------+---------+---------+-------------------------+------+------------------------------+

我怀疑这就是为什么MySQL会考虑子查询依赖,如果我可以孤立地执行它。

据我所知,在一个从属子查询中,MySQL为每个父查询行执行一次子查询,因此效率非常低。

有人可以在这里给我带来一些启示吗? 感谢。

1 个答案:

答案 0 :(得分:1)

我认为这是NOT IN(SELECT ...)。尝试使用LEFT JOIN

将其重写为IS NULL
SELECT 
  tid
FROM 
  ep_transaction_status ts
LEFT JOIN 
  ep_transaction_status ts2
USING (tid)
WHERE 
  ts.anulada IS NULL 
  AND ts.source = 'rake'
  AND ts2.anulada IS NULL
  AND ts2.timestamp > '2010-11-30 23:00:00'
  AND ts2.tid IS NULL

在我看来哪个BTW与

相同
SELECT 
  tid
FROM 
  ep_transaction_status ts
WHERE 
  ts.anulada IS NULL 
  AND ts.source = 'rake'
  AND ts.timestamp <= '2010-11-30 23:00:00'