MySQL性能优化(五)字符集不一致导致的隐式类型转换

俊达3年前技术文章1035

上一篇文章中,我们介绍了隐式类型转换。这里我们介绍另一种形式的隐式类型转换,由于字符集不一致,导致关联查询无法使用索引。


一个例子

SELECT * 
FROM funds
WHERE  uuid  in ( SELECT uuid FROM patients WHERE create_at != "0000-00-00 00:00:00" )


执行计划



首先优化器对查询做了一个转换,将in查询转换成关联查询

被驱动表funds的uuid上有唯一索引,但是执行计划中显示没有使用索引。


查看执行计划,

explain extended 
    select b.*
    from patients a, funds b
    where a.create_at != "0000-00-00 00:00:00" 
    and a.uuid=b.uuid
    
    
show warnings

select *
from patients a
     join funds b
where((a.create_at <> '0000-00-00 00:00:00')
and(a.uuid= convert(b.uuid using utf8mb4)))


发现对funds.uuid字段进行了类型转换。


我们查看一下表结构的定义,发现uuid的字符集不一致:

 CREATE TABLE `funds` ( 
     `id` int(11) NOT NULL AUTO_INCREMENT,  
     `uuid` varchar(128) COLLATE utf8_unicode_ci NOT NULL DEFAULT '' COMMENT 'UUID',
      …,
 PRIMARY KEY (`id`),  
UNIQUE KEY `uuid_idx` (`uuid`),) 
ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;


CREATE TABLE `patients` ( 
     `id` int(11) NOT NULL AUTO_INCREMENT,  
     `uuid` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '项目uuid',  
PRIMARY KEY (`id`),) 
ENGINE=InnoDB DEFAULT CHARSET=utf8mb4


funds.uuid 是utf8,而patients.uuid是utf8mb4。



我们在SQL中做一个处理,将驱动表的uuid字段字符集转换成utf8,匹配被驱动表的uuid字符集:

explain extended
 SELECT b.*
FROM (select convert(uuid using utf8) COLLATE utf8_unicode_ci as uuid
    from patients 
    where project_create_at != "0000-00-00 00:00:00") a, funds b
WHERE a.uuid = b.uuid


5-2.jpg


对SQL进行改写之后,可以看到,可以使用uuid字段上的索引。解决了查询的性能问题。


总结

同一个业务字段,在不同的表中数据类型和字符集要保持一致。这样可以避免表关联的时候发生隐式类型转换。

相关文章

PG的多版本并发控制(三)

三、多版本并发控制3.1 常见多版本并发的实现方式第一种方式是,数据库仅保存最新版本数据,将发生变更的旧行版本数据写到其他地方如undo,当需要读取旧版本数据时,通过undo重构。oracle和MyS...

impala:大数据交互查询

impala:大数据交互查询

一、简介        Cloudera公司推出,提供对HDFS、HBase数据的高性能、低延迟的交互式SQL查询功能。基于Hive,使用与Apache Hive相同的元数据,使用内存计算,兼顾数据仓...

Centos7 升级内核

1、查看当前内核版本$ uname -rsLinux 3.10.0-1160.45.1.el7.x86_642、安装 ELRepo# 载入公钥$ rpm --import https://www.el...

8.0 新特性-Generated Invisible Primary Key

8.0 新特性-Generated Invisible Primary Key

说明MySQL Innodb 引擎采用的是 IOT(索引组织表)存储方式,主键的重要性就不言而喻。在早期版本用户如果没有显式指定主键,会自动生成隐藏主键 row_id 来组织 B+ 树,隐藏主键 ro...

Kubernetes源码解读(六)-- Informer源码分析

Kubernetes源码解读(六)-- Informer源码分析

Informer 这个词的出镜率很高,我们在很多文章里都可以看到 Informer 的身影,但是我们在源码里真的去找一个叫做 Informer 的对象,却又发现找不到一个单纯的 Informer,但是...

Redis 命令行 redis-cli 介绍

前言redis-cli 是 Redis 自带的命令行工具,是运维和开发人员常用的工具,本篇文章将介绍它的使用技巧和一些有趣的功能。1. 连接 Redis 服务redis-cli 默认连接的是 127....

发表评论    

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。