空表情况下,优化器不用预定索引一次现象

错误描述:表行如下,表中数据为空,进行执行分析时候,发现优化器没有按照预定那样走第二条索引,很奇怪

mysql> show create table answer_survey_info\G
*************************** 1. row ***************************
Table: answer_survey_info
Create Table: CREATE TABLE `answer_survey_info` (
`answerId` bigint(64) NOT NULL AUTO_INCREMENT,
`surveyId` bigint(64) NOT NULL,
`questionId` bigint(64) NOT NULL,
`uin` varchar(255) DEFAULT NULL,
`userNumber` varchar(128) DEFAULT NULL,
`selectId` bigint(64) DEFAULT NULL,
`answerText` varchar(5000) DEFAULT NULL,
`emailAddress` varchar(64) DEFAULT NULL,
`ip` varchar(64) DEFAULT NULL,
`createTime` datetime DEFAULT NULL,
PRIMARY KEY (`answerId`),
KEY `surveyId_questionId_selectId_index` (`surveyId`,`questionId`,`selectId`),
KEY `surveyId_uin_index` (`uin`,`surveyId`)
) ENGINE=InnoDB AUTO_INCREMENT=10001 DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

mysql>
mysql>
mysql>
mysql>
mysql> show full columns from answer_survey_info;
+--------------+---------------+-----------------+------+-----+---------+----------------+---------------------------------+---------+
| Field | Type | Collation | Null | Key | Default | Extra | Privileges | Comment |
+--------------+---------------+-----------------+------+-----+---------+----------------+---------------------------------+---------+
| answerId | bigint(64) | NULL | NO | PRI | NULL | auto_increment | select,insert,update,references | |
| surveyId | bigint(64) | NULL | NO | MUL | NULL | | select,insert,update,references | |
| questionId | bigint(64) | NULL | NO | | NULL | | select,insert,update,references | |
| uin | varchar(255) | utf8_general_ci | YES | MUL | NULL | | select,insert,update,references | |
| userNumber | varchar(128) | utf8_general_ci | YES | | NULL | | select,insert,update,references | |
| selectId | bigint(64) | NULL | YES | | NULL | | select,insert,update,references | |
| answerText | varchar(5000) | utf8_general_ci | YES | | NULL | | select,insert,update,references | |
| emailAddress | varchar(64) | utf8_general_ci | YES | | NULL | | select,insert,update,references | |
| ip | varchar(64) | utf8_general_ci | YES | | NULL | | select,insert,update,references | |
| createTime | datetime | NULL | YES | | NULL | | select,insert,update,references | |
+--------------+---------------+-----------------+------+-----+---------+----------------+---------------------------------+---------+
10 rows in set (0.00 sec)

mysql>
mysql>
mysql>
mysql>

  

检查是否又是索引字符集的问题,由于是复合索引,使用他的左前缀的行作为索引行,发现都能够正常运行

mysql> explain select * from answer_survey_info where uin=‘15953‘;
+----+-------------+--------------------+------+--------------------+--------------------+---------+-------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------------------+------+--------------------+--------------------+---------+-------+------+-------------+
| 1 | SIMPLE | answer_survey_info | ref | surveyId_uin_index | surveyId_uin_index | 768 | const | 1 | Using where |
+----+-------------+--------------------+------+--------------------+--------------------+---------+-------+------+-------------+
1 row in set (0.00 sec)

mysql>
mysql>
mysql> explain select * from answer_survey_info where surveyId=10006;
+----+-------------+--------------------+------+------------------------------------+------------------------------------+---------+-------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------------------+------+------------------------------------+------------------------------------+---------+-------+------+-------+
| 1 | SIMPLE | answer_survey_info | ref | surveyId_questionId_selectId_index | surveyId_questionId_selectId_index | 8 | const | 1 | |
+----+-------------+--------------------+------+------------------------------------+------------------------------------+---------+-------+------+-------+
1 row in set (0.00 sec)

mysql>
mysql>

  

将第二索引的两行作为where判断,希望能走第二条索引(有个前提条件,第二条复合索引的右边行刚好是第一条索引的左前缀),结果如下,很是吃惊

mysql> explain select * from answer_survey_info where uin=‘15953‘ and surveyId=10006;
+----+-------------+--------------------+------+-------------------------------------------------------+------------------------------------+---------+-------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------------------+------+-------------------------------------------------------+------------------------------------+---------+-------+------+-------------+
| 1 | SIMPLE | answer_survey_info | ref | surveyId_questionId_selectId_index,surveyId_uin_index | surveyId_questionId_selectId_index | 8 | const | 1 | Using where |
+----+-------------+--------------------+------+-------------------------------------------------------+------------------------------------+---------+-------+------+-------------+
1 row in set (0.00 sec)

  

由于数据的分布会影响优化器做出执行计划,所以考虑往里面放上一些数据,下面的存储过程往里面插入了10w条数据

mysql> delimiter $$

mysql> create procedure test()
-> begin
-> declare num int;
-> set num=1;
-> while num <= 100000 do
-> insert into answer_survey_info values (null,FLOOR(RAND() * 10000),FLOOR(RAND() * 10000),FLOOR(RAND() * 10000),FLOOR(RAND() * 10000),FLOOR(RAND() * 10000),FLOOR(RAND() * 10000),FLOOR(RAND() * 10000),FLOOR(RAND() * 10000),now()); set num=num+1;
-> end while;
-> end;
-> $$
Query OK, 0 rows affected (0.00 sec)

mysql> call test();
-> $$
Query OK, 1 row affected (10.28 sec)

  

再次进行查询,现在已经正常了

mysql> explain select * from answer_survey_info where uin=‘2‘ and surveyId=1680;
+----+-------------+--------------------+------+-------------------------------------------------------+--------------------+---------+-------------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------------------+------+-------------------------------------------------------+--------------------+---------+-------------+------+-------------+
| 1 | SIMPLE | answer_survey_info | ref | surveyId_questionId_selectId_index,surveyId_uin_index | surveyId_uin_index | 776 | const,const | 1 | Using where |
+----+-------------+--------------------+------+-------------------------------------------------------+--------------------+---------+-------------+------+-------------+
1 row in set (0.00 sec)

mysql>
mysql>
mysql>

  

时间: 2024-09-30 11:37:34

空表情况下,优化器不用预定索引一次现象的相关文章

MySQL优化器不使用索引的情况

优化器选择不适用索引的情况 有时候,有乎其并没有选择索引而去查找数据,而是通过扫描聚集索引,也就是直接进行全表的扫描来得到数据.这种情况多发生于范围查找.JOIN链接操作等情况.例如 SELECT * FROM orderdetails WHERE orderid>10000 and orderid<102000; 通过SHOW INDEX FROM orderdetails可以看到 可以看到orderdetails有(orderID,ProductID)的联合主键.此外还有对于列OrderI

空a标签 a标签空的情况下 IE6 IE7下点击无效

最近做了好多网站专题页面,因为专题页面图片较多,个别banner上有1个到多个按钮,一种是用"图解img标签的usemap"的方法做链接,(图解img标签的usemap使用方法)[传送门] 另一种用则需要用空a标签来做,发现"a标签"在IE6与IE7中点击无效中点击不了("a标签"定义宽度和高度IE浏览器为零0),其他浏览器都正常(如果不正常请加"display:bolck;"(←推荐)或"float:left;&q

MySQL order by后对其他索引的干扰,导致优化器走错索引

MySQL version:5.5.36 [email protected] 5.5.36-log xxx 10:19:54>show index from FD_FINANCE_ACC_HIS;+--------------------+------------+------------------------+--------------+--------------+-----------+-------------+----------+--------+------+---------

SQL Server优化器特性-隐式谓词

原文:SQL Server优化器特性-隐式谓词 我们都知道,一条SQL语句提交给优化器会产生相应的执行计划然后执行输出结果,但他的执行计划是如何产生的呢?这可能是关系型数据库最复杂的部分了.这里我为大家介绍一个有关SQL Server优化器的特性-隐式谓词,并简单介绍在此特性下如何根据场景控制优化器的行为. 在这里我通过一个简单的实例来给大家说明下. code CREATE TABLE T1 (A INT, B INT) CREATE TABLE T2 (A INT, B INT) set sh

Sql Server查询性能优化之走出索引的误区

据了解绝大多数开发人员对于索引的理解都是一知半解,局限于大多数日常工作没有机会.也什么没有必要去关心.了解索引,实在哪天某个查询太慢了找到查询条件建个索引就ok,哪天又有个查询慢了,再建立个索引就是,或者干脆把整个查询SQL直接发给DBA,让DBA直接帮忙优化了,所以造成的状况就是开发人员对于索引的理解.认识很局限,以下就把我个人对于索引的理解及浅薄认识和大家分享下,希望能解除一些大家的疑惑,一起走出索引的误区 误区1.在表上建立了索引,在查询时用到了索引的列,索引就一定会生效 首先明确下这样的

Oracle优化器和优化模式

Oracle在执行一个SQL之前,首先要分析一下语句的执行计划,然后再按执行计划去执行.分析语句的执行计划的工作是由优化器(Optimizer) 来完成的.不同的情况,一条SQL可能有多种执行计划,但在某一时点,一定只有一种执行计划是最优的,花费时间是最少的.相信你一定会用Pl/sql Developer.Toad等工具去看一个语句的执行计划,不过你可能对Rule.Choose.First rows.All rows这几项有疑问,因为我当初也是这样的,那时我也疑惑为什么选了以上的不同的项,执行计

Oracle的优化器介绍

Oracle优化器介绍 本文讲述了Oracle优化器的概念.工作原理和使用方法,兼顾了Oracle8i.9i以及最新的10g三个版本.理解本文将有助于您更好的更有效的进行SQL优化工作. RBO优化器 RBO是一种基于规则的优化器,随着CBO优化器的逐步发展和完善,在最新的10g版本中Oracle已经彻底废除了RBO.正在使用Oracle8i或9i的人们或多或少的都会碰到RBO,因此在详细介绍CBO之前,我们有必要简单回顾一下古老的RBO优化器. 在RBO中Oracle根据可用的访问路径和访问路

PLSQL_性能优化系列04_Oracle Optimizer优化器

2014-09-25 BaoXinjian 一.摘要 1. Oracle优化器介绍 本文讲述了Oracle优化器的概念.工作原理和使用方法,兼顾了Oracle8i.9i以及最新的10g三个版本.理解本文将有助于您更好的更有效的进行SQL优化工作. 2. RBO优化器 RBO是一种基于规则的优化器,随着CBO优化器的逐步发展和完善,在最新的10g版本中Oracle已经彻底废除了RBO. 正在使用Oracle8i或9i的人们或多或少的都会碰到RBO,因此在详细介绍CBO之前,我们有必要简单回顾一下古

mysql如何查看索引使用情况以及优化

mysql中支持hash和btree索引.innodb和myisam只支持btree索引,而memory和heap存储引擎可以支持hash和btree索引 我们可以通过下面语句查询当前索引使用情况: show status like '%Handler_read%'; +-----------------------+-------+| Variable_name | Value |+-----------------------+-------+| Handler_read_first | 0