在 MySQL 中可以通过 explain 关键字模拟优化器执行 SQL语句,从而知道 MySQL 是如何处理 SQL 语句的。
• 客户端向 MySQL 服务器发送一条查询请求
• 服务器首先检查查询缓存,如果命中缓存,则立刻返回存储在缓存中的结果。否则进入下一阶段
• 服务器进行 SQL 解析、预处理、再由优化器生成对应的执行计划
• MySQL 根据执行计划,调用存储引擎的 API 来执行查询
• 将结果返回给客户端,同时缓存查询结果
注意:只有在8.0之前才有查询缓存,8.0之后查询缓存被去掉了
explain select 投影列 FROM 表名 WHERE 条件 ;

查询执行顺序:
id 值相同时表示从上向下执行
id 值相同被视为一组
如果是子查询,id 值会递增,id 值越高,优先级越高
id为NULL最后执行。
● simple:表示查询中不包含子查询或者 union
EXPLAIN select * from actor where id=1;

● primary:当查询中包含任何复杂的子部分,最外层的查询被标记成 primary
● derived:在 from 的列表中包含的子查询被标记成 derived
● subquery:在 select 或 where 列表中包含了子查询,则子查询被标记成 subquery
用个例子来了解primary、subquery和derived
set session optimizer_switch=‘derived_merge=off’;#关闭mysql5.7新特性对衍生表的合并优化
explain select (select 1 from actor where id = 1) from (select * from film where id = 1) der;

set session optimizer_switch=‘derived_merge=on’; #还原默认配置
● union:两个 select 查询时前一个标记为 PRIMARY,后一个标记为 UNION。union 出现在 from 从句子查询中,外层 select 标记为 PIRMARY,union 中第一个查询为 DERIVED,第二个子查询标记为 UNION
explain select 1 union all select 1;

● unionresult:从 union 表获取结果的 select 被标记成 union result 。
显示这一行的数据是关于哪张表的。
当 from 子句中有子查询时,table列是 格式,表示当前查询依赖 id=N 的查询,于是先执行 id=N 的查询。
当有 union 时,UNION RESULT 的 table 列的值为<union1,2>,1和2表示参与 union 的 select 行id。
这是重要的列,显示连接使用了何种类型。
SQL 性能优化的目标:至少要达到 range 级别,要求是 ref 级别,如果可以是 consts 最好。
说明:
1) consts 单表中最多只有一个匹配行(主键或者唯一索引),在优化阶段即可读取到数据。
2) ref 指的是使用普通的索引(normal index)。
3) range 对索引进行范围检索。
反例:explain 表的结果,type=index,索引物理文件全扫描,速度非常慢,这个 index 级别比较 range
还低,与全表扫描是小巫见大巫。
从最好到最差的连接类型为 system > const > eq_reg > ref > range > index > ALL。
一般来说,得保证查询达到range级别,最好达到ref
● NULL:mysql能够在优化阶段分解查询语句,在执行阶段用不着再访问表或索引。例如:在索引列中选取最小值,可以单独查找索引来完成,不需要在执行时访问表
explain select min(id) from film;

● system:表中只有一行数据。属于 const 的特例。如果物理表中就一行数据为 ALL
● const :查询结果最多有一个匹配行。因为只有一行,所以可以被视为常量。const 查询速度非常快,因为只读一次。一般情况下把主键或唯一索引作为唯一条件的查询都是 const
explain select * from (select * from film where id = 1) tmp;

● eq_ref:唯一性索引扫描,对于每个索引键,表中只有一条记录与之匹配。常见于主键或唯一索引扫描。
explain select * from film_actor left join film on film_actor.film_id = film.id

● ref:非唯一性索引扫描,返回匹配某个单独值得所有行。索引要和某个值相比较,可能会找到多个符合条件的行。
1.简单 select 查询,name是普通索引(非唯一索引)
explain select * from film where name = ‘film1’;

2.关联表查询,idx_film_actor_id是film_id和actor_id的联合索引,这里使用到了film_actor的左边前缀film_id部分
explain select film_id from film left join film_actor on film.id = film_actor.film_id;

● range:把这个列当作条件只检索其中一个范围。常见 where 从句中出现 between、<、>、>=、in 等。主要应用在具有索引的列中
explain select * from actor where id > 1;

● index:full index scan全索引扫描,index与all的区别为:index类型只遍历索引树,这通常比all快,因为索引文件通常比数据文件小。也就是说虽然index和all都是读全表,但index是从索引中读的,而all是从硬盘中读的。
explain select * from film;

● ALL:即全表扫描,扫描你的聚簇索引的所有叶子节点。通常情况下这需要增加索引来进行优化了。
explain select * from actor;

实际使用的索引。如果为 NULL,则没有使用索引。
如果想强制mysql使用或忽视possible_keys列中的索引,在查询中使用 forceindex、ignore index。
表示索引中使用的字节数,查询中使用的索引的长度(最大可能长度),并非实际使用长度,理论上长度越短越好。key_len 是根据表定义计算而得的,不是通过表内检索出的。
例子:
film_actor的联合索引 idx_film_actor_id 由 film_id 和 actor_id 两个int列组成,并且每个int是4字节。通过结果中的key_len=4可推断出查询使用了第一个列:film_id列来执行索引查找。
explain select * from film_actor where film_id = 2;


显示索引的哪一列被使用了,如果可能的话,是一个常量 const。
根据表统计信息及索引选用情况,大致估算出找到所需的记录所需要读取的行数。注意这个不是结果集里的行数, 数值越低越好。
显示了通过条件过滤出的行数的百分比估计值。
MYSQL 如何解析查询的额外信息。
Distinct: MySQL 发现第 1 个匹配行后,停止为当前的行组合搜索更多的行。
Not exists:MySQL 能够对查询进行 LEFT JOIN 优化,发现 1 个匹配 LEFT JOIN 标准的行后,不再为前面的的行组合在该表内检查更多的行。
range checked for each record (index map: #):MySQL 没有发现好的可以使用的索引,但发现如果来自前面的表的列值已知,可能部分索引可以使用。
Using filesort: 说明mysql会对数据使用**一个外部的索引排序,而不是按照表内的索引顺序进行读取。Mysql中无法利用索引完成的排序操作称为“文件排序”**这种情况下一般也是要考虑使用索引来优化的。
4.1. actor.name未创建索引,会浏览actor整个表,保存排序关键字name和对应的id,然后排序name并检索行记录
explain select * from actor order by name;

4.2. film.name建立了idx_name索引,此时查询时extra是using index
explain select * from film order by name;

Using index: 表示相应的select操作中使用了覆盖索引,避免访问了表的数据行,效率不错!
如果同时出现了using where,表明索引被用来执行索引键值的查找;
如果没有同时出现using where,表明索引用来读取数据而非执行查找动作
explain select film_id from film_actor where film_id = 1;

Using temporary:为了解决查询,MySQL 需要创建一个临时表来容纳结果。使用了临时表保存中间结果。常见于排序order by和分组查询group by。
Using filesort和Using temporary都是不太好的结果,会影响性能。
6.1. actor.name没有索引,此时创建了张临时表来distinct
explain select distinct name from actor;

6.2. film.name建立了idx_name索引,此时查询时extra是using index,没有用临时表
explain select distinct name from film;

Using where: 表示使用了where过滤。
explain select * from actor where name = ‘a’;
Using sort_union(…), Using union(…), Using intersect(…): 这 些 函 数 说 明 如 何 为index_merge 联接类型合并索引扫描。
Using index for group-by:类似于访问表的 Using index 方式,Using index for group-by 表示MySQL发现了一个索引,可以用来查 询GROUP BY或DISTINCT查询的所有列,而不要额外搜索硬盘访问实际的表。
我在使用omniauth/openid时遇到了一些麻烦。在尝试进行身份验证时,我在日志中发现了这一点:OpenID::FetchingError:Errorfetchinghttps://www.google.com/accounts/o8/.well-known/host-meta?hd=profiles.google.com%2Fmy_username:undefinedmethod`io'fornil:NilClass重要的是undefinedmethodio'fornil:NilClass来自openid/fetchers.rb,在下面的代码片段中:moduleNetclass
我遵循了教程http://gettingstartedwithchef.com/,第1章。我的运行list是"run_list":["recipe[apt]","recipe[phpap]"]我的phpapRecipe默认Recipeinclude_recipe"apache2"include_recipe"build-essential"include_recipe"openssl"include_recipe"mysql::client"include_recipe"mysql::server"include_recipe"php"include_recipe"php::modul
我在用Ruby执行简单任务时遇到了一件奇怪的事情。我只想用每个方法迭代字母表,但迭代在执行中先进行:alfawit=("a".."z")puts"That'sanalphabet:\n\n#{alfawit.each{|litera|putslitera}}"这段代码的结果是:(缩写)abc⋮xyzThat'sanalphabet:a..z知道为什么它会这样工作或者我做错了什么吗?提前致谢。 最佳答案 因为您的each调用被插入到在固定字符串之前执行的字符串文字中。此外,each返回一个Enumerable,实际上您甚至打印它。试试
如何检查Ruby文件是否是通过“require”或“load”导入的,而不是简单地从命令行执行的?例如:foo.rb的内容:puts"Hello"bar.rb的内容require'foo'输出:$./foo.rbHello$./bar.rbHello基本上,我想调用bar.rb以不执行puts调用。 最佳答案 将foo.rb改为:if__FILE__==$0puts"Hello"end检查__FILE__-当前ruby文件的名称-与$0-正在运行的脚本的名称。 关于ruby-检查是否
文章目录一、概述简介原理模块二、配置Mysql使用版本环境要求1.操作系统2.mysql要求三、配置canal-server离线下载在线下载上传解压修改配置单机配置集群配置分库分表配置1.修改全局配置2.实例配置垂直分库水平分库3.修改group-instance.xml4.启动监听四、配置canal-adapter1修改启动配置2配置映射文件3启动ES数据同步查询所有订阅同步数据同步开关启动4.验证五、配置canal-admin一、概述简介canal是Alibaba旗下的一款开源项目,Java开发。基于数据库增量日志解析,提供增量数据订阅&消费。Git地址:https://github.co
//1.验证返回状态码是否是200pm.test("Statuscodeis200",function(){pm.response.to.have.status(200);});//2.验证返回body内是否含有某个值pm.test("Bodymatchesstring",function(){pm.expect(pm.response.text()).to.include("string_you_want_to_search");});//3.验证某个返回值是否是100pm.test("Yourtestname",function(){varjsonData=pm.response.json
我从Ubuntu服务器上的RVM转移到rbenv。当我使用RVM时,使用bundle没有问题。转移到rbenv后,我在Jenkins的执行shell中收到“找不到命令”错误。我内爆并删除了RVM,并从~/.bashrc'中删除了所有与RVM相关的行。使用后我仍然收到此错误:rvmimploderm~/.rvm-rfrm~/.rvmrcgeminstallbundlerecho'exportPATH="$HOME/.rbenv/bin:$PATH"'>>~/.bashrcecho'eval"$(rbenvinit-)"'>>~/.bashrc.~/.bashrcrbenvversions
我有一个使用SeleniumWebdriver和Nokogiri的Ruby应用程序。我想选择一个类,然后对于那个类对应的每个div,我想根据div的内容执行一个Action。例如,我正在解析以下页面:https://www.google.com/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=puppies这是一个搜索结果页面,我正在寻找描述中包含“Adoption”一词的第一个结果。因此机器人应该寻找带有className:"result"的div,对于每个检查它的.descriptiondiv是否包含单词“adoption
我写了一个非常简单的rake任务来尝试找到这个问题的根源。namespace:foodotaskbar::environmentdoputs'RUNNING'endend当在控制台中执行rakefoo:bar时,输出为:RUNNINGRUNNING当我执行任何rake任务时会发生这种情况。有没有人遇到过这样的事情?编辑上面的rake任务就是写在那个.rake文件中的所有内容。这是当前正在使用的Rakefile。requireFile.expand_path('../config/application',__FILE__)OurApp::Application.load_tasks这里
我看到其他人也遇到过类似的问题,但没有一个解决方案对我有用。0.3.14gem与其他gem文件一起存在。我已经完全按照此处指示完成了所有操作:https://github.com/brianmario/mysql2.我仍然得到以下信息。我不知道为什么安装程序指示它找不到include目录,因为我已经检查过它存在。thread.h文件存在,但不在ruby目录中。相反,它在这里:C:\RailsInstaller\DevKit\lib\perl5\5.8\msys\CORE\我正在运行Windows7并尝试在Aptana3中构建我的Rails项目。我的Ruby是1.9.3。$gemin