`

mysql or条件可以使用索引而避免全表

阅读更多

        在某些情况下,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';“即可,如下所示:


 

文章来源:http://blog.csdn.net/hguisu/article/details/7106159

  • 大小: 3.8 KB
  • 大小: 7.1 KB
分享到:
评论

相关推荐

    MySQL的or、in、union与索引优化

    ### MySQL的or、in、union与索引优化 在数据库查询优化中,索引的使用至关重要,它能显著提升查询速度。本文将基于一个具体的业务场景来探讨在MySQL中使用`union all`、`in`、`or`以及负向查询(如`!=`)时如何有效...

    mysql中or是否走索引详解

    2. **覆盖索引**:如果`OR`操作符连接的条件都在同一个索引的所有列中,那么这个索引被称为覆盖索引,MySQL可以只使用索引来完成查询,而无需回表,这样会提高查询效率。 3. **索引合并(Index Merge)**:MySQL ...

    有关mysql面试题和索引原理理解

    2. 应尽量避免在 WHERE 子句中使用 OR 来连接条件,否则将导致引擎放弃使用索引而进行全表扫描。 3. 应尽量避免在 WHERE 子句中对字段进行表达式操作,这将导致引擎放弃使用索引而进行全表扫描。 4. 应尽量避免在 ...

    MySQL索引原理及慢查询优化1

    例如,避免在索引列上使用函数,减少全表扫描,合理使用JOIN操作,以及避免在WHERE子句中使用OR连接条件,这些都可以显著提高查询效率。 5. **磁盘IO与预读** 磁盘IO是数据库性能的关键瓶颈,因为磁盘读取速度远...

    mysql 千万级数据优化

    4. 避免在 WHERE 子句中使用 OR 来连接条件,否则将导致引擎放弃使用索引而进行全表扫描。 5. IN 和 NOT IN 也要慎用,否则会导致全表扫描。 6. 如果在 WHERE 子句中使用参数,也会导致全表扫描。 7. 避免在 WHERE ...

    mysql优化提高百万条数据的查询速度[参考].pdf

    4. 应尽量避免在where子句中使用or连接条件,否则将导致引擎放弃使用索引而进行全表扫描。可以使用union all来代替or连接。 5. in和not in也要慎用,否则会导致全表扫描。对于连续的数值,能用between就不要用in了...

    浅谈MySQL中优化sql语句查询常用的30种方法.doc

    3. 应尽量避免在 where 子句中使用 or 来连接条件,否则将导致引擎放弃使用索引而进行全表扫描。 4. 应尽量避免在 where 子句中使用 in 和 not in,否则将导致全表扫描。 三、避免函数运算 5. 应尽量避免在 where ...

    MySQL数据库索引失效的10种场景.zip

    当`OR`连接两个条件时,即使这两个条件都涉及索引,MySQL也可能选择全表扫描。可以尝试使用UNION ALL或者重构查询来改善性能。 **5. 使用函数或表达式** 在查询中对索引列应用函数或表达式,如`DATE(column)`,会...

    mysql优化提高百万条数据的查询速度.pdf

    优化 MySQL 查询速度需要从多方面入手,包括建立索引、避免全表扫描、避免使用或、in、not in、!= 等操作符,避免在 where 子句中对字段进行表达式操作、函数操作等。只有遵循这些经验和原则,才能提高 MySQL 查询...

    mysql面试题,以及经典的索引问题详解

    4. **索引覆盖**:如果查询仅涉及索引列,MySQL可以直接使用索引而不是回表,这被称为索引覆盖。 5. **索引的维护成本**:插入、删除和更新操作会涉及到索引的维护,可能导致性能下降。 6. **如何避免全表扫描**:...

    MySQL 索引及优化实战1

    2. `UNION`、`IN` 和 `OR` 查询:`UNION` 和 `IN` 均能利用索引,`OR` 在新版 MySQL 中也可以,但`IN` 通常更高效,推荐使用 `IN` 代替 `OR`。 3. 负向条件查询:如 `!=`、`<>`、`NOT IN`、`NOT EXISTS`、`NOT LIKE`...

    MYSQL执行计划及索引最佳实践

    它可以帮助我们了解MySQL是如何处理SQL语句的,包括哪些索引被使用、表是如何被连接的以及查询优化器是如何工作的。 - **基本用法**: - `EXPLAIN SELECT * FROM table;`:展示基本的执行计划。 - `EXPLAIN ...

    MySQL中or、in、union与索引优化详析

    3. `SELECT * FROM order WHERE status=0 OR date ()` 这个查询中,`OR`操作可能会影响索引的使用,除非MySQL能智能地处理这种情况,否则可能会导致全表扫描。 总结来说,优化MySQL查询时,应优先考虑使用`IN`操作...

    MySQL查询条件中in会用到索引吗

    如果查询仅涉及`IN`中的列,并且这些列构成索引的前导列,那么MySQL可能会执行索引覆盖,直接从索引中获取数据,而不访问实际的表行,这样可以提高查询速度。 5. **优化`IN`查询**: 有时候,将`IN`语句改写为多...

    mysql索引优化.rar

    MySQL数据库在数据处理中扮演着至关重要的角色,而索引是提升查询性能的关键工具。本资料包"mysql索引优化.rar"聚焦于MySQL的索引优化,旨在帮助你理解和掌握如何有效利用索引来提高数据库的运行效率。以下将详细...

    导致MySQL索引失效的一些常见写法总结

    1. **全表扫描(Full Table Scan)**:当查询涉及所有或大部分数据时,MySQL会选择不使用索引而进行全表扫描。例如,使用`SELECT * FROM table`会忽略所有索引。 2. **非等值比较**:索引通常适用于等值查询,如`...

    mysql关于索引的面试题

    2. **联合索引**:如果在联合索引的条件中,只有部分列被用作等值查询,而后面的列被用作范围查询,那么从范围查询的列开始的索引将不会被使用。 3. **不等于操作(!= 或 )**:不等于操作通常不会利用到索引,除非...

    接口响应慢的处理办法-mysql索引不生效情况分析

    为所有可能出现在`OR`条件中的字段建立索引,或重构查询逻辑以避免使用`OR`。 2. **字段类型不匹配** - **问题描述**: 如果字段类型是字符串,但在查询时未使用引号包裹值,则可能导致索引失效。 - **示例**...

    mysql优化_提高百万条数据的查询速度

    4. **避免使用 OR 连接条件**:OR 会迫使数据库放弃索引。可以将多个条件拆分为多个查询,然后使用 UNION ALL 合并结果。 5. **慎用 IN 和 NOT IN**:对于连续数值,使用 BETWEEN 操作符替代 IN,可以提高效率。...

Global site tag (gtag.js) - Google Analytics