mysql - WHERE 语句中的 OR 的全表扫描

标签 mysql sql database explain

所以我有这个问题

EXPLAIN SELECT r.* FROM r_table r
        LEFT JOIN f_table f ON f.id = r.fid
        LEFT JOIN f_table ff ON r.fid = 0 AND r.type = 'f' AND r.id = ff.id
      WHERE (r.fid = 0 AND ff.cid = 421563) OR (r.fid <> 0 AND f.cid = 421563);

它正在对表 r 执行全表扫描

解释输出:

1   SIMPLE      r   ALL Index1              2314    Using where
1   SIMPLE      f   eq_ref  PRIMARY PRIMARY 4   r.fid   1   Using where
1   SIMPLE      ff  eq_ref  PRIMARY PRIMARY 4   r.id    1   Using where

如何修改此查询使其不执行全表扫描? 我知道我可能会使用 UNION,但除非必要,否则我宁愿不使用 UNION。

编辑

将查询重写为 UNION 确实有效...这是 UNION 查询

EXPLAIN SELECT r.* FROM r_table r
        LEFT JOIN f_table f ON r.fid <> 0 AND f.id = r.fid
      WHERE f.cid = 421563
UNION SELECT r.* FROM r_table r
        LEFT JOIN f_table ff ON r.fid = 0 AND r.obj_type = 'f' AND r.obj_id = ff.id
      WHERE ff.cid = 421563;

并解释输出

'2', 'UNION', 'ff', 'ref', 'PRIMARY,cid', 'cid', '4', 'const', '2', 'Using where; Using index'
'2', 'UNION', 'r', 'ref', 'Index1,obj_id_type', 'Index1', '13', 'const,const,ff.id', '1', 'Using where'
'1', 'PRIMARY', 'f', 'ref', 'PRIMARY,cid', 'cid', '4', 'const', '2', 'Using where; Using index'
'1', 'PRIMARY', 'r', 'ref', 'Index1', 'Index1', '4', 'f.id', '1', ''
NULL, 'UNION RESULT', '<union1,2>', 'ALL', NULL, NULL, NULL, NULL, NULL, ''

但再一次,我宁愿不为此做 UNION

最佳答案

只需将 ff.cid 和 f.cid 上的过滤器从 where 子句移动到连接。事实上,由于您正在执行左连接,因此您无论如何都必须这样做。

关于mysql - WHERE 语句中的 OR 的全表扫描,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15072093/

相关文章:

MySQL:检查第一个字符是否_not_ A-Z

sql - sql中如何创建INNER JOIN多个表

c# - SQL类型和加密大小

mysql - SQL - 使用 2 个不同 ID 从列返回数据

mysql - 我怎样才能画出我的数据库设计?

sql - 使用表别名 UPSERT 来自另一个数据库的表

mysql - Hibernate:查询日期范围

php - 在 null/while 更新查询上调用成员函数 bind_param()

PHP 高级搜索 - 多个参数

python - 使用 MySQL Connector 和 Python 3 在 Django 中运行 inspectdb 时出错