在某些情况下,or条件可以避免全表扫描的。虽然在我在MariaDB10.0.10版本和MySQL5.7.14上都测试不成功,但还是很有必要记录下来。
mysql> show variables like 'version'; +---------------+---------------------+ | Variable_name | Value | +---------------+---------------------+ | version | 10.0.10-MariaDB-log | +---------------+---------------------+ 1 row in set (0.00 sec)
mysql> show variables like 'version'; +---------------+------------+ | Variable_name | Value | +---------------+------------+ | version | 5.7.14-log | +---------------+------------+ 1 row in set, 1 warning (0.00 sec)
一.where 语句里面如果带有or条件, myisam表能用到索引,innodb不行
1.myisam表
CREATE TABLE IF NOT EXISTS `a` ( `id` int(1) NOT NULL AUTO_INCREMENT, `uid` int(11) NOT NULL, `aNum` char(20) DEFAULT NULL, PRIMARY KEY (`id`), KEY `uid` (`uid`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=6;
mysql> explain select * from a where id=1 or uid =2; +----+-------------+-------+-------------+---------------+-------------+---------+------+------+---------------------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+-------------+---------------+-------------+---------+------+------+---------------------------------------+ | 1 | SIMPLE | a | index_merge | PRIMARY,uid | PRIMARY,uid | 4,4 | NULL | 2 | Using union(PRIMARY,uid); Using where | +----+-------------+-------+-------------+---------------+-------------+---------+------+------+---------------------------------------+ 1 row in set (0.00 sec)
2.innodb表
CREATE TABLE IF NOT EXISTS `a` ( `id` int(1) NOT NULL AUTO_INCREMENT, `uid` int(11) NOT NULL, `aNum` char(20) DEFAULT NULL, PRIMARY KEY (`id`), KEY `uid` (`uid`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=6;
mysql> explain select * from a where id=1 or uid =2; +----+-------------+-------+------+---------------+------+---------+------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+---------------+------+---------+------+------+-------------+ | 1 | SIMPLE | a | ALL | PRIMARY,uid | NULL | NULL | NULL | 5 | Using where | +----+-------------+-------+------+---------------+------+---------+------+------+-------------+ 1 row in set (0.00 sec)
二.必须所有的or条件都必须是独立索引
+-------+---------------------------------------------------------------------------------------------------------------------- | Table | Create Table +-------+---------------------------------------------------------------------------------------------------------------------- | a | CREATE TABLE `a` ( `id` int(1) NOT NULL AUTO_INCREMENT, `uid` int(11) NOT NULL, `aNum` char(20) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM AUTO_INCREMENT=6 DEFAULT CHARSET=latin1 | +-------+---------------------------------------------------------------------------------------------------------------------- 1 row in set (0.00 sec)
explain查看:
mysql> explain select * from a where id=1 or uid =2; +----+-------------+-------+------+---------------+------+---------+------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+---------------+------+---------+------+------+-------------+ | 1 | SIMPLE | a | ALL | PRIMARY | NULL | NULL | NULL | 5 | Using where | +----+-------------+-------+------+---------------+------+---------+------+------+-------------+ 1 row in set (0.00 sec)
全表扫描了。
三.用UNION替换OR (适用于索引列)
通常情况下, 用UNION替换WHERE子句中的OR将会起到较好的效果,对索引列使用OR将造成全表扫描。
注意,以上规则只针对多个索引列有效,如果有column没有被索引,查询效率可能会因为你没有选择OR而降低。
在下面的例子中,LOC_ID 和REGION上都建有索引。
高效:
select loc_id , loc_desc , region from location where loc_id = 10 union select loc_id , loc_desc , region from location where region = "melbourne"
低效:
select loc_id , loc desc , region from location where loc_id = 10 or region = "melbourne"
如果你坚持要用OR, 那就需要返回记录最少的索引列写在最前面。
四.用in来替换or
这是一条简单易记的规则,但是实际的执行效果还须检验,在oracle8i下,两者的执行路径似乎是相同的。
低效:
select * from location where loc_id = 10 or loc_id = 20 or loc_id = 30
高效:
select * from location where loc_in in (10,20,30);
PS:查看mysql版本的方法
1.在命令行输入“mysql --version",按”Enter“键即可,如下图所示:
2.使用命令行查看mysql版本-mysql变量查看
在命令行输入“mysql",按”Enter“进入mysql命令行模式,输入”show variables like 'version';“即可,如下所示:
相关推荐
### MySQL的or、in、union与索引优化 在数据库查询优化中,索引的使用至关重要,它能显著提升查询速度。本文将基于一个具体的业务场景来探讨在MySQL中使用`union all`、`in`、`or`以及负向查询(如`!=`)时如何有效...
2. **覆盖索引**:如果`OR`操作符连接的条件都在同一个索引的所有列中,那么这个索引被称为覆盖索引,MySQL可以只使用索引来完成查询,而无需回表,这样会提高查询效率。 3. **索引合并(Index Merge)**:MySQL ...
2. 应尽量避免在 WHERE 子句中使用 OR 来连接条件,否则将导致引擎放弃使用索引而进行全表扫描。 3. 应尽量避免在 WHERE 子句中对字段进行表达式操作,这将导致引擎放弃使用索引而进行全表扫描。 4. 应尽量避免在 ...
例如,避免在索引列上使用函数,减少全表扫描,合理使用JOIN操作,以及避免在WHERE子句中使用OR连接条件,这些都可以显著提高查询效率。 5. **磁盘IO与预读** 磁盘IO是数据库性能的关键瓶颈,因为磁盘读取速度远...
4. 避免在 WHERE 子句中使用 OR 来连接条件,否则将导致引擎放弃使用索引而进行全表扫描。 5. IN 和 NOT IN 也要慎用,否则会导致全表扫描。 6. 如果在 WHERE 子句中使用参数,也会导致全表扫描。 7. 避免在 WHERE ...
4. 应尽量避免在where子句中使用or连接条件,否则将导致引擎放弃使用索引而进行全表扫描。可以使用union all来代替or连接。 5. in和not in也要慎用,否则会导致全表扫描。对于连续的数值,能用between就不要用in了...
3. 应尽量避免在 where 子句中使用 or 来连接条件,否则将导致引擎放弃使用索引而进行全表扫描。 4. 应尽量避免在 where 子句中使用 in 和 not in,否则将导致全表扫描。 三、避免函数运算 5. 应尽量避免在 where ...
当`OR`连接两个条件时,即使这两个条件都涉及索引,MySQL也可能选择全表扫描。可以尝试使用UNION ALL或者重构查询来改善性能。 **5. 使用函数或表达式** 在查询中对索引列应用函数或表达式,如`DATE(column)`,会...
优化 MySQL 查询速度需要从多方面入手,包括建立索引、避免全表扫描、避免使用或、in、not in、!= 等操作符,避免在 where 子句中对字段进行表达式操作、函数操作等。只有遵循这些经验和原则,才能提高 MySQL 查询...
4. **索引覆盖**:如果查询仅涉及索引列,MySQL可以直接使用索引而不是回表,这被称为索引覆盖。 5. **索引的维护成本**:插入、删除和更新操作会涉及到索引的维护,可能导致性能下降。 6. **如何避免全表扫描**:...
2. `UNION`、`IN` 和 `OR` 查询:`UNION` 和 `IN` 均能利用索引,`OR` 在新版 MySQL 中也可以,但`IN` 通常更高效,推荐使用 `IN` 代替 `OR`。 3. 负向条件查询:如 `!=`、`<>`、`NOT IN`、`NOT EXISTS`、`NOT LIKE`...
它可以帮助我们了解MySQL是如何处理SQL语句的,包括哪些索引被使用、表是如何被连接的以及查询优化器是如何工作的。 - **基本用法**: - `EXPLAIN SELECT * FROM table;`:展示基本的执行计划。 - `EXPLAIN ...
3. `SELECT * FROM order WHERE status=0 OR date ()` 这个查询中,`OR`操作可能会影响索引的使用,除非MySQL能智能地处理这种情况,否则可能会导致全表扫描。 总结来说,优化MySQL查询时,应优先考虑使用`IN`操作...
如果查询仅涉及`IN`中的列,并且这些列构成索引的前导列,那么MySQL可能会执行索引覆盖,直接从索引中获取数据,而不访问实际的表行,这样可以提高查询速度。 5. **优化`IN`查询**: 有时候,将`IN`语句改写为多...
MySQL数据库在数据处理中扮演着至关重要的角色,而索引是提升查询性能的关键工具。本资料包"mysql索引优化.rar"聚焦于MySQL的索引优化,旨在帮助你理解和掌握如何有效利用索引来提高数据库的运行效率。以下将详细...
1. **全表扫描(Full Table Scan)**:当查询涉及所有或大部分数据时,MySQL会选择不使用索引而进行全表扫描。例如,使用`SELECT * FROM table`会忽略所有索引。 2. **非等值比较**:索引通常适用于等值查询,如`...
2. **联合索引**:如果在联合索引的条件中,只有部分列被用作等值查询,而后面的列被用作范围查询,那么从范围查询的列开始的索引将不会被使用。 3. **不等于操作(!= 或 )**:不等于操作通常不会利用到索引,除非...
为所有可能出现在`OR`条件中的字段建立索引,或重构查询逻辑以避免使用`OR`。 2. **字段类型不匹配** - **问题描述**: 如果字段类型是字符串,但在查询时未使用引号包裹值,则可能导致索引失效。 - **示例**...
4. **避免使用 OR 连接条件**:OR 会迫使数据库放弃索引。可以将多个条件拆分为多个查询,然后使用 UNION ALL 合并结果。 5. **慎用 IN 和 NOT IN**:对于连续数值,使用 BETWEEN 操作符替代 IN,可以提高效率。...