我在优化mySQL查询时遇到了一些问题,我一直在使用子查询来尝试根据查询中的ID获取上一个和下一个ID。当我在mySQL中使用EXPLAIN
函数时,它表明我的一个子查询正在运行690k +行,这是我猜测会影响性能的原因。
我试图限制子查询仅返回一个结果,并在子查询中使用了MIN
和MAX
,但是这两个选项仍返回大行集。
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
答案 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
说明:将c
与cp
连接在一起,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似乎对您的查询是正确的。