如何使用子查询更好地优化此mySQL查询

时间:2019-01-24 17:11:08

标签: mysql subquery query-optimization

我在优化mySQL查询时遇到了一些问题,我一直在使用子查询来尝试根据查询中的ID获取上一个和下一个ID。当我在mySQL中使用EXPLAIN函数时,它表明我的一个子查询正在运行690k +行,这是我猜测会影响性能的原因。

我试图限制子查询仅返回一个结果,并在子查询中使用了MINMAX,但是这两个选项仍返回大行集。

SELECT c.*, (SELECT id FROM cards WHERE id > '733290' ORDER BY id ASC LIMIT 1) AS 'prev', (SELECT id FROM cards WHERE id < '733290' ORDER BY id DESC LIMIT 1) AS 'next' FROM cards c LEFT JOIN albums a ON (a.id = cs.album_id) WHERE c.id = '733290'

在解释中,这是结果:

id
select_type
table
type
possible_keys
key
key_len
ref
rows
Extra

5
SUBQUERY
cards
range
PRIMARY,user_id
PRIMARY
4
NULL
696177
Using where

4
SUBQUERY
cards
range
PRIMARY,user_id
PRIMARY
4
NULL
4
Using where

编辑:这是纸牌表的定义:

Keyname    Type    Unique  Packed  Column  Cardinality Collation   Null    Comment
PRIMARY BTREE   Yes No  id  696183  A   No  
user_id BTREE   No  No  user_id 5438    A   No  
album   BTREE   No  No  album   258 A   No

2 个答案:

答案 0 :(得分:1)

尝试一下:

SELECT c.*, cp.id AS `prev`, cn.id AS `next`
FROM cards c
LEFT JOIN cards cp ON c.id < cp.id
LEFT JOIN cards cpp ON c.id < cpp.id AND cp.id > cpp.id
LEFT JOIN cards cn ON c.id > cn.id
LEFT JOIN cards cnn ON c.id > cnn.id AND cn.id < cnn.id
WHERE c.id = 733290
 AND cpp.id IS NULL
 AND cnn.id IS NULL

说明:将ccp连接在一起,ID具有更大的ID,但还要确保ID在之间 {{ 1}}和cpp是一个空集。也就是说,外部联接必须返回NULL。

c.id执行相同操作。

答案 1 :(得分:0)

EXPLAIN提供虚假信息,尤其是在涉及LIMIT时。

您的查询是最佳的,并且在每个方向上实际接触的行不会超过1。

(而且我还没有弄清楚Bill想要实现什么!)

要获得更可靠的触摸行数,请执行以下操作:

FLUSH STATUS;
SELECT ...;
SHOW SESSION STATUS LIKE 'Handler_read%';

对于类似的查询(在具有310万行的表上),我得到了

+-----------------------+-------+
| Variable_name         | Value |
+-----------------------+-------+
| Handler_read_first    | 0     |
| Handler_read_key      | 3     |
| Handler_read_last     | 0     |
| Handler_read_next     | 0     |
| Handler_read_prev     | 0     |
| Handler_read_rnd      | 0     |
| Handler_read_rnd_next | 0     |
+-----------------------+-------+

将数字加起来(得到3);恰好是(?)触摸了多少行。 3似乎对您的查询是正确的。