MYSQL之ICP、MRR、BKA

Index Condition Pushdown(ICP)

Index Condition Pushdown (ICP)是mysql使用索引从表中检索行数据的一种优化方式。

ICP原理

禁用ICP,存储引擎会通过遍历索引定位基表中的行,然后返回给MySQL Server层,再去为这些数据行进行WHERE后的条件的过滤。

开启ICP,如果部分WHERE条件能使用索引中的字段,MySQL Server 会把这部分下推到存储引擎层,存储引擎通过索引过滤,把满足的行从表中读取出。ICP能减少引擎层访问基表的次数和MySQL Server 访问存储引擎的次数。

ICP的目标是减少从基表中全纪录读取操作的数量,从而降低IO操作

对于InnoDB表,ICP只适用于辅助索引。

ICP标识

当使用ICP优化时,执行计划的Extra列显示Using indexcondition提示

Continue reading

PHP连接mysql8.0出错“SQLSTATE[HY000] [2054] The server requested authentication method unknown to”的解决办法

错误信息

SQLSTATE[HY000] [2054] The server requested authentication method unknown to…

这个错可能是mysql默认使用caching_sha2_password作为默认的身份验证插件,而不再是mysql_native_password,但是客户端暂时不支持这个插件导致的。官方文档说明

In MySQL 8.0, caching_sha2_password is the default authentication plugin rather than mysql_native_password. For information about the implications of this change for server operation and compatibility of the server with clients and connectors, see caching_sha2_password as the Preferred Authentication Plugin.

在MySQL 8.0中,caching_sha2_password是默认的身份验证插件,而不是mysql_native_password。有关此更改对服务器操作的影响以及服务器与客户端和连接器的兼容性的信息,请参阅caching_sha2_password作为首选身份验证插件。

解决方法一:修改MySQL全局配置文件

编辑my.cnf文件,更改默认的身份认证插件。

$ vi /etc/my.cnf

[mysqld]中添加下边的代码

default_authentication_plugin=mysql_native_password

然后重启mysql

$ service mysqld restart

解决方法二:修改密码认证方式

ALTER USER 'YOURUSERNAME'@'localhost' IDENTIFIED WITH mysql_native_password BY 'YOURPASSWORD';

官方文档:https://dev.mysql.com/doc/refman/8.0/en/caching-sha2-pluggable-authentication.html

使用Dockerfile构建Swoole+php7环境

01
02
03
04
05
06
07
08
09
10
11
12
13
14
FROM php:7.2.7-cli
RUN apt-get update
    && apt-get install -y libmemcached-dev zlib1g-dev
    
RUN pecl install redis-4.0.1
    && pecl install swoole-4.0.1
    && pecl install memcached-3.0.4
    && pecl install xdebug-2.6.0
    && docker-php-ext-enable redis swoole memcached xdebug
    
COPY . /usr/src/myapp
WORKDIR /usr/src/myapp
CMD [ "php", "-m" ]

构建完环境后,使用方法见:https://blog.haohtml.com/archives/17925

这里推荐另一种更简单的方法 https://github.com/mlocati/docker-php-extension-installer,同时支持多个PHP版本,唯一的不足可能是安装时没有办法指定扩展的版本号或者手动修改脚本文件来完成。

推荐文章:Dockerfile 最佳实践

MySQL中的查询开销查看方法

MySQL使用基于成本的优化器,它尝试预测一个查询使用某种执行计划时的成本,并选择其中成本最小的一个。在MySQL可以通过查询当前会话的last_query_cost的值来得到其计算当前查询的成本。

mysql> select * from t_message limit 10;
...省略结果集

mysql> show status like 'last_query_cost';
+-----------------+-------------+
| Variable_name   | Value       |
+-----------------+-------------+
| Last_query_cost | 6391.799000 |
+-----------------+-------------+

示例中的结果表示优化器认为大概需要做6391个数据页的随机查找才能完成上面的查询。这个结果是根据一些列的统计信息计算得来的,这些统计信息包括:每张表或者索引的页面个数索引的基数索引数据行的长度索引的分布情况等等。

有非常多的原因会导致MySQL选择错误的执行计划,比如统计信息不准确、不会考虑不受其控制的操作成本(用户自定义函数、存储过程)、MySQL认为的最优跟我们想的不一样(我们希望执行时间尽可能短,但MySQL值选择它认为成本小的,但成本小并不意味着执行时间短)等等。

这里last_query_cost的值是io_costcpu_cost的开销总和,它通常也是我们评价一个查询的执行效率的一个常用指标。

(1)它是作为比较各个查询之间的开销的一个依据。

(2)它只能检测比较简单的查询开销,对于包含子查询和union的查询是测试不出来的。

(3)当我们执行查询的时候,MySQL会自动生成一个执行计划,也就是query  plan,而且通常有很多种不同的实现方式,它会选择最低的那一个,而这个cost值就是开销最低的那一个。

(4)它对于比较我们的开销是非常有用的,特别是我们有好几种查询方式可选的时候。

一个docker-compose微服务脚本,自用

容器为swoole+php7

docker-compose.yml

version: '3.6'
services:
  redis:
    image: redis
  web:
    image: cfanbo/swoole4_php7:v1
    depends_on:
      - redis
    links:
      - redis
    volumes:
      - /Users/sxf/sites/msgserve:/usr/src/myapp
    command: "php /usr/src/myapp/src/wx_push_server.php start"

对于 wx_push_server.php文件里redis的主机地址应该写成docker-compose配置文件里的容器服务名(redis)