items表和links表进行关联,
我们执行一个复合查询:
SELECT count(*) FROM items WHERE id IN (SELECT id FROM items_links);
结果返回10条数据。
直接执行子查询语句,发现结果并不一致:
我们将查询语句拆分成两个子查询:
SELECT id FROM items_links;
SELECT count(*) FROM items WHERE id IN ...
我们发现id字段并不存在,因此问题得到定位。
tips:将符合查询语句拆分成多个子查询逐层定位,是发现复杂查询语句问题的好办法。
EXPLAIN EXTENDED SELECT count(*) FROM items WHERE id IN (SELECT id FROM items_links)\G
show warnings\G
继续查看实际的执行子查询情况:
我们发现,实际的子查询中的id并没有在关联表中获取,因此问题得以定位。
tips:EXPLAIN EXTENDED和show warnings是个很好用的工具
我们创建一个表,插入了一些数据
此时,我们想删除t1和t2中所有的数据。
mysql> DELETE FROM t1, t2 USING t1, t2;
Query OK, 0 rows affected (0.00 sec)
我们发现影响行数为0.
tips: 在实际的应用软件开发时,要注意实际影响行数,保证数据操作符合预期。
我们尝试将DELETE语句转换成SELECT语句,查看待删除的数据有哪些
mysql> SELECT * FROM t1, t2;
Empty set (0.00 sec)
此时发现查询语句实际返回行数也是0,确认了删除语句并没有实际删除数据,我们使用EXPLAIN EXTENDED进一步查看实际执行情况
mysql> EXPLAIN EXTENDED SELECT * FROM t1, t2\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: t1
type: system
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 1
filtered: 100.00
Extra:
*************************** 2. row ***************************id: 2
select_type: SIMPLE SUBQUERY
table: t2
type: system
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 0
filtered: 0.00
Extra: const row not found 2 rows in set, 1 warning (0.03 sec)
Note (Code 1003): select '1' AS `f1`,'0' AS `f2` from `test`.`t1` join `test`.`t2`
我们发现,实际上这个查询把两个表join了一下,取出并集,而t2表中是没有数据的,因此结果为空。
tips:update,delete语句会修改数据,因此在排查问题时,一般将其转换成SELECT,进一步使用explain extended 锁定原因。