• [技术干货] 多级部署MySql数据库
      在日常运维工作中,当对服务器进行批量安装MySql数据库时,一台一台的安装将会浪费大量的时间、人力等资源、这时就需要用户进行多机部署MySql数据库,如下:vim mysql_install.sh#!/bin/bash#mysql install 2#by tianze#Yumrm -rf /etc/yum.repos.d/*wget ftp://172.16.8.100/yumrepo/CentOs 7.repo -p /etc/yum.repos.d/wget ftp://172.16.8.100/yumrepo/Mysql 157.repo -p /etc/yum.repos.d/yum -y install 1ftp vim-enhanced bash-completion#Firewalld &SeLinuxsystemctl stop firewalld; systemctl disable firewalldsetenforce 0; sed -ri '/^SELINUX/c\SELINUX=disabled'/etc/selinux/config#ntpyum -y install chronysed -ri '/3.centos/a\server 172.16.5.100 iburst ' /etc/chrony.confsystemctl start chronyd; systemctl enable chronyd#install mysql5.7yum -y install mysql-community-serversystemctl start mysqldsystemctl enable mysqldgrep 'temporary password '/var/log/mysql.log |awk '{print SNF}'>/root/mysqloldpass.txtmysqladmin ''-uroot-p'' cat /root/mysqloldpass.txt ''password''{Tianze123}  上述代码首先下载了yum源,安装vim工具,接着关闭防火墙和selinux、更新系统时间,然后开始安装MySQL数据库,代码是在一台机器上实现的部署Mysql。然而项目要求是堕胎机器实现部署Mysql,因此,使用shell循环实现多台服务器部署MYSQL,具体代码如下:vim ip.txt10.0.104.510.0.104.2710.0.104.3410.0.104.13610.0.104.108vim main.sh#!bin/bash#mainwhile read ipdo{ping -c 1-w 2$ip >/dev/nullif{$? -eq0};thenscp -r mysql_install.sh root@$ip:/tmp/ssh root@$ip ''/tmp/mysql_install.sh''}$done<ip.txtwaitecho "all finsh..."以上代码是针对ip.txt文件中的主机IP地址进行多级部署MySQL。首先是ping一下ip.txt 中的ip地址。判断机器是否正常,然后把安装mysql脚本复制到多台服务器上/tmp/下,远程使用管理员权限执行安装Mysql脚本。如果显示All finsh.... 则表示所有服务器安装已完成。
  • [问题求助] 【鲲鹏服务器】【编译安装mysql】【openEuler】【openssl】编译安装mysql报错
    【服务器信息】操作系统openEuler23,cpu鲲鹏【主要内容】我参考patch使用说明-MySQL OLAP并行优化特性-基础加速特性-鲲鹏BoostKit数据库使能套件-文档首页-鲲鹏社区 (hikunpeng.com)优化mysql,按照教程操作,在使用cmake编译安装mysql的时候出现如下错误错误信息提示我没有安装openssl,我就去执行安装,发现系统已经存在openssl然后去网上找结局方法,我看有的openssl是1.1版本的,我就去装1.1的版本,结果还是报没有openssl错误
  • [技术干货] MySQL函数find_in_set介
    场景介绍 人有时会身兼数职,需要查找出其中担任某一职务的都有哪些人,如下面position字段,不同的职务用数字表示,多个职务以逗号隔开。 先要查找出担任1职务的人员,通过以下两种方式来查询。 方式一 采用模糊查询,匹配出1职务的记录,如下SQL: select * from user where position like '%1%' 查询结果如下,仔细观察你会发现position为10的也被查出来了,但这个不符合业务要求。 方式二 采用MySQL的原生函数find_in_set(str,array)来查询,SQL如下: select * from user where find_in_set(1,position) 查询结果如下,符合要求。 函数介绍 FIND_IN_SET(str,strlist),注意其中strlist只识别英文逗号。 ———————————————— 原文链接:https://blog.csdn.net/loongshawn/article/details/78611636 
  • [互动交流] HECS(云耀云服务器) mysql问题 经常被重置服务被关闭
    mysql经常被重置服务被关闭?是因为网站没有备案吗你们有遇到这个问题吗还是我的镜像有问题隔几天服务器上的mysql就会被重置,包括服务会被关闭
  • [专题汇总] 技术干货30篇,一次看过瘾。速进。
     大家好7月给大家带来codeArts板块的技术干货30篇合集,免去爬楼烦恼,希望可以帮到大家。  1.Nginx反向代理后,web服务器获取真实访问IP的方法【转】 https://bbs.huaweicloud.com/forum/thread-0212126166776222008-1-1.html  2.Eclipse中maven项目报错: org.springframework.web.filter.CharacterEncodingFilter https://bbs.huaweicloud.com/forum/thread-0212126166611645007-1-1.html  3.如何将公司外网数据库部署到客户内网服务器中,以MySQL为例【转】     https://bbs.huaweicloud.com/forum/thread-0218126166402927009-1-1.html  4.Mysql分组查询每组最新的一条数据(三种实现方法)【转】 https://bbs.huaweicloud.com/forum/thread-0212126166137614006-1-1.html  5.服务端回调报错。Cookie 的 domain 传入非法字符 【转】 https://bbs.huaweicloud.com/forum/thread-0284126165918635010-1-1.html  6.Java获取HttpServletRequest request中所有参数的方法【转】 https://bbs.huaweicloud.com/forum/thread-0249126165722109058-1-1.html  7.Java下载文件的几种方式【转】 https://bbs.huaweicloud.com/forum/thread-0284126165496966009-1-1.html  8.Python工程实践之np.loadtxt()读取数据 https://bbs.huaweicloud.com/forum/thread-0284126154810611008-1-1.html  9.python中的extend功能及用法【转】 https://bbs.huaweicloud.com/forum/thread-0218126154771208007-1-1.html  10.Python isalnum()函数的具体使用【转】 https://bbs.huaweicloud.com/forum/thread-0227126154735209007-1-1.html  11.Python endswith()函数的具体使用【转】 https://bbs.huaweicloud.com/forum/thread-0283126154645130002-1-1.html  12.Python Requests使用Cookie的几种方式详解【转】 https://bbs.huaweicloud.com/forum/thread-0205126154329369004-1-1.html  13.Python大批量写入数据(百万级别)的方法【转】 https://bbs.huaweicloud.com/forum/thread-0227126154192353006-1-1.html  14.python自动化神器pyautogui使用步骤【转】 https://bbs.huaweicloud.com/forum/thread-0249126153906646056-1-1.html  15.Python 获取图片GPS等信息锁定图片拍摄地点、拍摄时间(实例代码)【转】 https://bbs.huaweicloud.com/forum/thread-0212126153709428005-1-1.html  16.python绘制ROC曲线的示例代码【转】 https://bbs.huaweicloud.com/forum/thread-0284126153513019006-1-1.html  17.Python中map函数的技巧分享【转】 https://bbs.huaweicloud.com/forum/thread-0227126153401950004-1-1.html  18.Python列表pop()函数使用实例详解【转】 https://bbs.huaweicloud.com/forum/thread-0222126153273615007-1-1.html  19.使用Pandas计算系统客户名称的相似度【转】 https://bbs.huaweicloud.com/forum/thread-0283126152370390001-1-1.html  20.Python字典get()函数使用详解【转】 https://bbs.huaweicloud.com/forum/thread-0212126152189966004-1-1.html  21.Python集合add()函数使用详解【转】 https://bbs.huaweicloud.com/forum/thread-0218126152083399006-1-1.html  22.python中Scikit-learn库的高级特性和实践分享【转】 https://bbs.huaweicloud.com/forum/thread-0218126152004011005-1-1.html  23.MapUtils工具类【转】 https://bbs.huaweicloud.com/forum/thread-0222125918123973044-1-1.html  24.HTTP响应的状态码415解决【转】 https://bbs.huaweicloud.com/forum/thread-0283125917982618029-1-1.html  25.js保留两位小数方法总结【转】 https://bbs.huaweicloud.com/forum/thread-0222125917923319043-1-1.html  26.聊聊springboot项目引用第三平台私有jar踩到的坑【转】 https://bbs.huaweicloud.com/forum/thread-0284125917178124048-1-1.html  27.如何利用mysql5.7提供的虚拟列来提高查询效率【转】 https://bbs.huaweicloud.com/forum/thread-0284125916421713047-1-1.html  28.怎样修改检查约束条件 https://bbs.huaweicloud.com/forum/thread-0284125913342309042-1-1.html  29.【MySQL新手入门系列五】:MySQL的高级特性简介及MySQL的安全简介-转载 https://bbs.huaweicloud.com/forum/thread-0284125377030598012-1-1.html  30.【SQL应知应会】行列转换(二)• MySQL版-转载 https://bbs.huaweicloud.com/forum/thread-0249125376948578009-1-1.html 
  • [技术干货] oracle与mysql语法差异
    由于自己在云服务器上面一直安装的是mysql,但是有一个网上的项目用的是oracle数据库。现在就是1.安装oracle。2.修改项目里使用的oracle语法 改为mysql。oracle12C mysql8按照速度效率来说可能第一种更好,不过自己学习的过程就是在于折腾尝试吧 。刚好也是参考网上的一些教程以及自己的实际情况。整理下oracle切换mysql的注意事项,以及语法比较。注意事项语法差异:Oracle和MySQL在SQL语法方面存在一些差异。需要仔细检查和修改项目中的SQL语句,以适应MySQL的语法规则。例如,日期处理、分页查询和字符串连接等方面可能会有不同的语法。数据类型:Oracle和MySQL支持的数据类型可能有所不同。确保将Oracle中使用的数据类型映射到MySQL中相对应的数据类型。特别注意字符集和长度限制的区别。主键和索引:在Oracle中,主键和索引是分开创建的,而在MySQL中,可以将主键作为索引的一部分。在迁移过程中,需要检查并相应调整表的主键和索引定义。存储过程和触发器:项目使用了Oracle的存储过程和触发器,需要将其转换为MySQL兼容的方式。MySQL使用不同的语法和特性来定义和执行存储过程和触发器。数据迁移和兼容性:将数据从Oracle迁移到MySQL可能会涉及到数据类型的转换和数据导出/导入。确保数据迁移过程中的数据完整性和一致性,并进行适当的测试以验证数据在MySQL中的正确性和兼容性。性能差异:Oracle和MySQL在性能和优化方面有一些差异。在迁移后,需要重新评估查询性能和调整数据库配置参数,以充分利用MySQL的性能优势。安全性和权限:MySQL和Oracle在安全性和权限管理方面存在差异。确保将用户、角色和权限正确地迁移到MySQL,并进行必要的安全设置和访问控制。语法差异数据类型差异:字符串类型:Oracle中使用VARCHAR2,MySQL中使用VARCHAR。字符类型:Oracle中使用CHAR,MySQL中使用CHAR。数值类型:Oracle中的NUMBER可以映射到MySQL的DECIMAL或NUMERIC。日期和时间类型:Oracle中使用DATE,MySQL中使用DATE或DATETIME。字符串连接操作符:Oracle使用"||"进行字符串连接,例如:SELECT column1 || column2 FROM table;MySQL使用"CONCAT"函数进行字符串连接,例如:SELECT CONCAT(column1, column2) FROM table;分页查询语法:Oracle中使用ROWNUM来限制查询结果集的行数,例如:SELECT * FROM table WHERE ROWNUM <= 10;MySQL中使用LIMIT来限制查询结果集的行数,例如:SELECT * FROM table LIMIT 10;获取自增主键值的方式:Oracle使用序列(Sequence)来获取自增主键值,例如:SELECT sequence_name.NEXTVAL FROM dual;MySQL使用AUTO_INCREMENT属性来实现自增主键,插入数据后可以使用LAST_INSERT_ID()函数获取生成的主键值。空值处理:Oracle中使用NULL,MySQL中使用NULL。在Oracle中,空字符串('')和NULL是等效的,而在MySQL中它们是不同的。以上是对oracle转换mysql数据库的注意事项和语法差异的整理,也是给自己做一个备份记录,也希望可以帮到大家。
  • [技术干货] mysql如何快速备份部分数据
    在MySQL中,您可以使用多种方法来快速备份部分数据。以下是一些常用的备份方法:使用SELECT INTO OUTFILE语句: 这个方法适用于将表中的数据导出到一个文本文件中。您可以使用SELECT INTO OUTFILE语句将查询结果导出到一个CSV文件或其他格式中。这个方法适用于备份部分表数据。SELECT column1, column2, ... INTO OUTFILE '/path/to/backup_file.csv' FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' LINES TERMINATED BY '\n' FROM your_table WHERE your_condition;请替换具体的列名、备份文件路径、表名以及筛选条件。使用mysqldump命令: mysqldump是MySQL提供的备份工具,可以备份整个数据库或部分数据。通过使用--where参数,您可以指定一个条件来备份部分数据。mysqldump -u username -p --where="your_condition" your_database your_table > backup_file.sql请替换相应的用户名、数据库名、表名以及备份文件名和条件。使用物理备份工具: 有一些第三方物理备份工具(例如Percona XtraBackup),它们可以在不停止MySQL数据库的情况下备份数据库文件,因此备份速度更快。这些工具通常也支持备份部分数据。请注意,备份部分数据可能会导致备份不完整,特别是如果备份的数据之间存在关联关系。在进行备份时,确保备份的数据是完整且符合应用程序的需求。另外,无论采用何种备份方法,请务必定期进行备份,并将备份文件存储在安全的位置。
  • [技术干货] 如何将公司外网数据库部署到客户内网服务器中,以MySQL为例【转】
    1、登录Mysql数据库/usr/local/mysql/bin/mysql -u数据库用户名 -p数据库密码如果本地服务器上登录被禁止(只允许客户端登录),则使用如下方法上传mysql客户端到应用服务器上任意位置链接:cid:link_0提取码:lwey进入文件所在目录,并执行安装命令cd /data/ rpm -ivh MySQL-client-5.6.36-1.linux_glibc2.5.x86_64.rpm进入文件所在目录,并执行登录命令cd /data/ mysql -h 192.168.16.131 -uu_plan -pHnhtmuF8utTy2、创建数据库show databases; create database 数据库名称; show databases;3、切换使用刚创建的数据库use 数据库名称;4、上传sql文件到服务器任何位置例如:/home/developer/test.sql5、运行sql文件source /home/developer/test.sql;6、查询sql文件中的表是否正常创建了show tables;7、退出Mysql命令模式\q
  • [技术干货] Mysql分组查询每组最新的一条数据(三种实现方法)【转】
    1. 准备模拟SQLDROP TABLE IF EXISTS `customer_wallet_detail`;CREATE TABLE `customer_wallet_detail` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `customer_id` bigint(20) NULL DEFAULT NULL COMMENT '用户ID', `happen_amount` varchar(15) NULL DEFAULT '0' COMMENT '发生金额 带'-'号的代表扣款', `balance_amount` varchar(15) NULL DEFAULT '0' COMMENT '可用余额', `create_time` bigint(20) NULL DEFAULT NULL COMMENT '发生时间', PRIMARY KEY (`id`) USING BTREE) ENGINE = InnoDB COMMENT = '用户钱包明细' ; INSERT INTO `test`.`customer_wallet_detail`(`id`, `customer_id`, `happen_amount`, `balance_amount`, `happen_time`) VALUES (1, 1, '100', '100', 1670300656630);INSERT INTO `test`.`customer_wallet_detail`(`id`, `customer_id`, `happen_amount`, `balance_amount`, `happen_time`) VALUES (2, 1, '-10', '90', 1670300656640);INSERT INTO `test`.`customer_wallet_detail`(`id`, `customer_id`, `happen_amount`, `balance_amount`, `happen_time`) VALUES (3, 1, '5', '95', 1670300656650);INSERT INTO `test`.`customer_wallet_detail`(`id`, `customer_id`, `happen_amount`, `balance_amount`, `happen_time`) VALUES (4, 3, '998', '998', 1670300656660);INSERT INTO `test`.`customer_wallet_detail`(`id`, `customer_id`, `happen_amount`, `balance_amount`, `happen_time`) VALUES (5, 3, '-100', '898', 1670300656670);INSERT INTO `test`.`customer_wallet_detail`(`id`, `customer_id`, `happen_amount`, `balance_amount`, `happen_time`) VALUES (6, 3, '-98', '800', 1670300656680);INSERT INTO `test`.`customer_wallet_detail`(`id`, `customer_id`, `happen_amount`, `balance_amount`, `happen_time`) VALUES (7, 2, '666', '666', 1670300656690);INSERT INTO `test`.`customer_wallet_detail`(`id`, `customer_id`, `happen_amount`, `balance_amount`, `happen_time`) VALUES (8, 2, '-66', '600', 1670300656695);INSERT INTO `test`.`customer_wallet_detail`(`id`, `customer_id`, `happen_amount`, `balance_amount`, `happen_time`) VALUES (9, 2, '-600', '0', 1670300656699);2. 错误查询SELECT * FROM ( SELECT * FROM customer_wallet_detail ORDER BY create_time DESC ) t1 GROUP BY t1.customer_id;错误原因在mysql5.7以及之后的版本,如果GROUP BY的子查询中包含ORDER BY,但是 GROUP BY 不与 LIMIT 配合使用,ORDER BY会被忽略掉,所以子查询在 GROUP BY 时排序不会生效,可能是因为子查询大多数是作为一个结果给主查询使用,所以子查询不需要排序。3. 方法一鉴于以上的原因我们可以添加上 LIMIT 条件来实现功能。PS:这个LIMIT的数量可以先自行 COUNT 出你要遍历的数据条数(这个数据条数是所有满足查询条件的数据合,我这里共9条数据)SELECT * FROM ( SELECT * FROM customer_wallet_detail ORDER BY create_time DESC LIMIT 9 ) t1 GROUP BY t1.customer_id;4. 方法二(适用于自增ID和创建时间排序一致)方法一需要先COUNT查询然后将查询结果设置到LIMIT条件中比较麻烦,这里还可以使用MAX()函数来实现该功能。PS:因为我这里的业务数据是有序插入的,使用主键自增id和create_time结果是一样的而且使用id查询效率更高,如果没有唯一且有序的id可以替代create_time那么就用方案一,不能直接使用 SELECT id,MAX(create_time) 这种操作来获取最新一条数据id原因在总结中有详细描述。SELECT *FROM customer_wallet_detail WHERE id IN ( SELECT MAX( id ) FROM customer_wallet_detail GROUP BY customer_id ) ORDER BY customer_id;5. 方法三(适用于自增ID和创建时间排序一致)方法三和方法二实现逻辑基本一致只是将IN查询替换成了连接查询,本地20w条数据测试 方法三比方法二性能提升50%,有兴趣的可以增大数据集测试后续性能变化。SELECT t1.*FROM customer_wallet_detail t1INNER JOIN ( SELECT MAX(id) AS id FROM customer_wallet_detail GROUP BY customer_id) t2 ON t1.id = t2.id 6. 总结结合我的业务经过测试,目前看来方案三是最合适的,sql简单性能适中,方案一比方案二性能更差而且实现麻烦,最终选择那个方案主要看业务而定。MAX()函数和MIN()这一类函数和GROUP BY配合使用存在问题MAX()函数和MIN()这一类函数和GROUP BY配合使用,GROUP BY拿到的数据永远都是这个分组排序最上面的一条,而MAX()函数和MIN()这一类函数会将这个分组中最大 | 最小的值取出来,这样会导致查询出来的数据对应不上。正确查询:错误查询:这里的确拿到每个分组最新创建时间了但是拿的数据id还是排序的第一条转载自https://blog.javaex.cn/article/detail/554826155808583680
  • [技术干货] 优化MySQL语句的常见方案汇总
    优化MySQL的SQL语句可以提高数据库的性能和响应时间。以下是一些优化MySQL SQL语句的方法:使用索引:为经常使用的查询语句创建索引,可以加快查询速度。索引可以加速ORDER BY、GROUP BY、JOIN等操作。减少使用SELECT *:查询不必要的列会降低查询速度,尽量只查询需要的列。使用预准备语句:预准备语句可以减少SQL解析和编译的时间,提高查询效率。避免使用LIKE操作:LIKE操作会使用全表扫描,查询速度慢,可以使用前缀匹配或者正则表达式来代替。避免使用子查询:子查询会使查询计划变得复杂,执行效率低下。尽量使用join来代替。减少使用事务:对于读密集型的操作,使用事务会降低效率。可以批量处理数据,减少事务的开启和关闭次数。使用EXPLAIN语句:EXPLAIN语句可以查看查询计划,了解MySQL如何执行查询语句。可以根据查询计划来优化查询语句。优化数据库结构:合理的数据库结构可以提高查询效率。例如,将经常使用的数据放在一个表中,不经常使用的数据放在另一个表中。调整MySQL配置:可以通过调整MySQL配置来提高MySQL的性能。例如,调整innodb_buffer_pool_size、query_cache_size等参数。定期清理和优化数据库:定期清理不再需要的数据,优化数据库表结构,可以提高MySQL的性能和稳定性。以上是优化MySQL SQL语句的一些方法,需要根据具体的业务场景和数据结构进行优化。 另外,EXPLAIN 是 MySQL 数据库中用来分析查询语句性能的工具。它可以提供查询语句的执行计划,告诉你在执行查询语句时 MySQL 是如何处理的。通过分析执行计划,可以找到查询语句的瓶颈,从而提高查询效率。EXPLAIN 语句通常用于调试查询语句,了解查询计划是如何生成的,以及索引如何被使用等。在查询语句后面添加 EXPLAIN 关键字,可以查看该查询语句的执行计划。执行计划会提供以下信息:id:查询序列号。select_type:查询类型,包括简单查询、主查询、union 查询、子查询等。table:输出行所引用的表。type:联接类型。possible_keys:可能使用的索引。key:实际使用的索引。key_len:索引字段长度。ref:联接使用的列。rows:扫描的行数。filtered:按照 WHERE 子句过滤后的行数占比。extra:额外的信息,包括使用临时表、使用文件排序等。通过分析 EXPLAIN 语句的输出,可以找到查询语句的瓶颈,并针对性地优化查询语句。常见的优化方法包括:优化查询语句中的 WHERE 子句、使用索引、优化联接类型、减少使用子查询、减少使用事务等。
  • [技术干货] Explain详解
     EXPLAIN是MySQL中一个非常实用的工具,它可以帮助我们分析SQL语句的执行计划,从而找出性能瓶颈并进行优化。在EXPLAIN命令中,每个字段都有特定的含义和用法,下面就来详细介绍一下。  1. id:查询的标识符,它是AUTO_INCREMENT列的值加1。  2. select_type:查询类型,包括SIMPLE(简单查询)、PRIMARY(主查询)、SUBQUERY(子查询)、DERIVED(派生表查询)等。  3. table:查询涉及的表名。  4. type:连接类型,包括ALL(全表扫描)、index(索引扫描)、range(范围扫描)等。  5. possible_keys:可能使用的索引。  6. key:实际使用的索引。如果没有使用索引,则为NULL。  7. key_len:使用的索引的长度。  8. ref:显示索引的哪一列被使用了。如果是常数,则表示该列被用于筛选行;如果是表达式或函数,则表示该列的值被用于筛选行。  9. rows:MySQL预计需要扫描的行数。如果rows的值很大,说明查询可能存在性能问题。  10. Extra:包含不适合在其他列中显示的额外信息,如Using index(使用覆盖索引)、Using filesort(使用文件排序)等。  通过分析EXPLAIN命令的结果,我们可以找出SQL语句中的性能瓶颈,比如是否使用了合适的索引、是否需要添加或调整索引、是否需要更改查询语句等等。因此,掌握EXPLAIN命令的用法和每个字段的含义非常重要,可以帮助我们编写出更高效、更优质的SQL语句。 
  • [技术干货] 如何利用mysql5.7提供的虚拟列来提高查询效率【转】
    在我们日常开发过程中,有时候因为对索引列进行函数调用,导致索引失效。举个例子,比如我们要按月查询记录,而当我们 表中只存时间,如果我们使用如下语句,其中create_time为索引列select count(*) from user where MONTH(create_time) = 5虽然可能查到正确的结果,但通过explain我们会发现没走索引。因此我们为了能确保使用索引,我们可能会改成select count(*) from user where create_time BETWEEN '2022-05-01' AND '2022-06-01';或者干脆在数据库表中冗余一个月份的列字段,并对这个月份创建索引。如果我们使用的mysql是5.7版本,我们则可以使用mysql5.7版本提供的一个新特性--虚拟列来达到上述效果虚拟列在mysql5.7支持2种虚拟列virtual columns 和 stored columns 。两者的区别是virtual 只是在读行的时候计算结果,但在物理上是不存储,因此不占存储空间,且仅在InnoDB引擎上建二级索引,而stored 则是当行数据进行插入或更新时计算并存储的,是需要占用物理空间的,支持在MyISAM和InnoDB引擎创建索引mysql5.7 默认的虚拟列类型为virtual columns01创建虚拟列语法ALTER TABLE 表名称 add column 虚拟列名称 虚拟列类型 [GENERATED ALWAYS] as (表达式) [VIRTUAL | STORED];02使用虚拟列注意事项a、衍生列的定义可以修改,但virtual和stored之间不能相互转换,必要时需要删除重建b、虚拟列字段只读,不支持 INSRET 和 UPDATEc、只能引用本表的非 generated column 字段,不可以引用其它表的字段d、使用的表达式和操作符必须是 Immutable 属性,比如不能使用 CONNECTION_ID(), CURRENT_USER(), NOW()e、可以将已存在的普通列转化为stored类型的衍生列,但virtual类型不行;同样的,可以将stored类型的衍生列转化为普通列,但virtual类型的不行f、虚拟列定义不允许使用自增 (AUTO_INCREMENT),也不允许使用自增基列g、虚拟列允许修改表达式,但不允许修改存储方式(只能通过删除重新创建来修改)h、如果虚拟列用作索引,会有一个缺点值会存储两次。一次用作虚拟列的值,一次用作索引中的值03虚拟列的使用场景a、虚拟列可以简化和统一查询,将复杂条件定义为生成的列,可以在查询时直接使用虚拟列(代替视图)b、存储虚拟列可以用作实例化缓存,以用于动态计算成本高昂的复杂条件c、虚拟列可以模拟功能索引,并且可以使用索引,这对与无法直接使用索引的列(JSON 列)非常有用示例因为mysql5.7也支持json列,因此本示例就以json和虚拟列为例子演示一下示例01创建示例表CREATE TABLE `t_user_json` (   `id` int NOT NULL AUTO_INCREMENT,   `user_info` json DEFAULT NULL,   `create_time` datetime DEFAULT CURRENT_TIMESTAMP,   PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;02创建虚拟列注: 虚拟列可以在建表语句时候,直接创建即可。本示例是为了突出虚拟列语法ALTER TABLE t_user_json ADD COLUMN v_user_name VARCHAR(50) GENERATED ALWAYS AS (JSON_UNQUOTE(json_extract(user_info,'$.username')));正常我们的json语句如下{"age": 23, "email": "likairui@qq.com", "mobile": "89136682644", "fullname": "李凯瑞", "username": "likairui"}我们通过JSON_UNQUOTE来去除双引号,否则到时候生成的虚拟列v_user_name 的值会变成"likairui",而实际我们需要的字段值应该likairui因为mysql5.7的json不是本文的重点,本文就不论述了,如果对mysql5.7 json语法函数感兴趣的朋友可以查看如下链接https://dev.mysql.com/doc/refman/5.7/en/json-functions.html03为虚拟列创建索引ALTER TABLE t_user_json ADD INDEX idx_v_user_name(v_user_name);04查看生成的表数据05查看是否使用了索引EXPLAIN  SELECT  id,user_info,create_time,v_user_name AS username,v_date_month AS MONTH  FROM t_user_json WHERE (v_user_name = 'likairui')注: 在mysql8.0版本可以使用EXPLAIN ANALYZE,他可以查看sql的耗时情况EXPLAIN ANALYZE SELECT  id,user_info,create_time,v_user_name AS username,v_date_month AS MONTH  FROM t_user_json WHERE (v_user_name = 'cengwen')06代码层面的小细节因为虚拟列是不能进行插入和更新的,因此使用orm框架的时候,要特别注意这点。比如使用mybatis-plus时,要记得在实体的虚拟列的映射字段上加上如下注解@TableField(value = "v_user_name",insertStrategy = FieldStrategy.NEVER,updateStrategy = FieldStrategy.NEVER)     private String username;加上这个注解后,虚拟列字段就不会进行更新或者插入总结本文基于mysql5.7大体介绍了一下虚拟列,如果是使用mysql8.0.13以上的版本,可以函数索引,他的实现方式本质也是基于虚拟列实现。所谓的函数索引就是在创建索引的时候,支持使用函数表达式。比如ALTER TABLE user ADD INDEX((MONTH(create_time)));通过函数索引也可以很方便提高我们的查询效率。具体使用可以查看如下链接https://dev.mysql.com/doc/refman/8.0/en/create-index.html转载自https://mp.weixin.qq.com/s?__biz=MzI1MTY1Njk4NQ==&mid=2247504278&idx=1&sn=2b7c65ff7126c93f5c24cde09767e662&chksm=e9ed3fe0de9ab6f66c75f23caf5c88d05c1b8d14ea2e8c80ed2a3cfe8d43b3bc1850fa81fb6b&token=252819573&lang=zh_CN#rd
  • [技术干货] Mysql写热点分散优化
    在高并发场景下mysql为了保持事务的ACID特性在事务对数据进行更新时会对目标数据进行加锁,直到事务提交或回滚才结束。在同一时间同一行数据只有一个事务可以进行更新操作。因此并发的更新操作在数据库内是串行执行的,而且并发的冲突事务会触发死锁检测进一步影响性能。1.悲观锁select .... for update2.死锁检测mysql通过死锁检测(innodb_deadlock_detect)和死锁超时时间(innodb_lock_wait_timeout)这两个参数来解决死锁。热点行优化1.转update为insert2.将热点数据拆分到不同的库和表中(分库分表)分散热点数据。3.更新操作放入消息队列,流量削峰的形式异步处理。4.利用云数据库RDS对sql限流(阿里云)
  • [技术干货] MySQL:分库分表与分区的区别和思考
    一.分分合合  说过很多次,不要拘泥于某一个技术的一点,技术是相通的。重要的是编程思想,思想是最重要的。当数据量大的时候,需要具有分的思想去细化粒度。当数据量太碎片的时候,需要具有合的思想来粗化粒度。1.1 分  很多技术都运用了分的编程思想,这里来举几个例子,这些都是分的思想集中式服务发展到分布式服务从Collections.synchronizedMap(x)到1.7ConcurrentHashMap再到1.8ConcurrentHashMap,细化锁的粒度的同时依旧保证线程安全从AtomicInteger到LongAdder,ConcurrentHashMap的size()方法。用分散思想,减少cas次数,增强多线程对一个数的累加JVM的G1 GC算法,将堆分成很多Region来进行内存管理Hbase的RegionServer中,将数据分成多个Region进行管理平时开发是不是线程池都资源隔离2.2 合  很多技术也运用到了合的编程思想,这里举几个例子,这些都是合的思想TLAB(Thread Local Allocation Buffers),线程本地分配缓存。避免多线程冲突,提高对象分配效率逃逸分析,将变量的实例化内存直接在栈里分配,无需进入堆,线程结束栈空间被回收。减少临时对象在堆内分配数量CMS GC算法下,虽然使用标记清除,但是也有配置支持整理内存碎片。如:-XX:UseCMS-CompactAtFullCollection(FullGC后是否整理,Stop The World会变长)和-XX:CMSFullGCs-BeforeCompaction(几次FullGC之后进行压缩整理)锁粗化,当JIT发现一系列连续的操作都是对同一对象反复加锁和释放锁,会加大锁同步的范围kafka的网络数据传输有一些数据配置,减少网络开销。如:batch.size和linger.ms等等平时开发是不是都个叫批量获取接口回到顶部二.分区  本文一切基于MySql InnoDB  说了这么多,接下来说主体,先说分区,因为之前博主写过一篇MySql分区的博客所以这里不会多费笔墨来写,具体见:https://www.cnblogs.com/GrimMjx/p/10526821.html2.1 实现方式  具体如何实现上面链接里有写,这里只需记住如果表中存在主键或唯一索引时,分区列必须是唯一索引的一个组成部分。  这个是数据库分的,应用透明,代码无需修改任何东西。2.2 内部文件  先去data目录,如果不知道目录位置的可以执行:  接下来看下内部文件:  从上图我们可以看出,有2中类型的文件,.frm文件和.ibd文件.frm文件:表结构文件.ibd文件:InnoDB中,索引和数据都在同个文件.ibdata(你的执行结果可能是.MYD索引文件和.MYI数据文件,没关系,这是MyIsAm存储引擎,对应着InnoDB的.ibd文件)。因为Order这张表分为5个区,所以有5个这样的文件.par文件:你执行的结果可能有.par文件也可能没有。注意:从MySql 5.7.6开始,不再创建.par分区定义文件。分区定义存储在内部数据字典中。2.3 数据处理  分区表后,提高了MySql性能。如果一张表的话,那就只有一个.ibd文件,一颗大的B+树。如果分表后,将按分区规则,分成不同的区,也就是一个大的B+树,分成多个小的树。  (PS:如果想研究一颗聚集索引B+树可以放多少行数据,请看:https://www.cnblogs.com/GrimMjx/p/10540263.html)  读的效率肯定提升了,如果走分区键索引的话,先走对应分区的辅助索引B+树,再走对应分区的聚集索引B+树。  如果没有走分区键,将会在所有分区都会执行一次。会造成多次逻辑IO!平时开发如果想查看sql语句的分区查询可以使用explain partitons select xxxxx语句。可以看到一句select语句走了几个分区。mysql> explain partitions select \* from TxnList where startTime>'2016-08-25 00:00:00' and startTime<'2016-08-25 23:59:00'; +----+-------------+-------------------+------------+------+---------------+------+---------+------+-------+-------------+ | id | select\_type | table | partitions | type | possible\_keys | key | key\_len | ref | rows | Extra | +----+-------------+-------------------+------------+------+---------------+------+---------+------+-------+-------------+ | 1 | SIMPLE | ClientActionTrack | p20160825 | ALL | NULL | NULL | NULL | NULL | 33868 | Using where | +----+-------------+-------------------+------------+------+---------------+------+---------+------+-------+-------------+ row in set (0.00 sec)回到顶部三.分库分表  当一张表随着时间和业务的发展,库里表的数据量会越来越大。数据操作也随之会越来越大。一台物理机的资源有限,最终能承载的数据量、数据的处理能力都会受到限制。这时候就会使用分库分表来承接超大规模的表,单机放不下的那种。  区别于分区的是,分区一般都是放在单机里的,用的比较多的是时间范围分区,方便归档。只不过分库分表需要代码实现,分区则是mysql内部实现。分库分表和分区并不冲突,可以结合使用。3.1 实现3.1.1 分库分表标准存储占用100G+数据增量每天200w+单表条数1亿条+3.1.2 分库分表字段  分库分表字段取值非常重要在大多数场景该字段是查询字段数值型  一般使用userId,可以满足上述条件3.2 分布式数据库中间件  分布式数据库中间件分为两种,proxy和客户端式架构。proxy模式有MyCat、DBProxy等,客户端式架构有TDDL、Sharding-JDBC等。那么proxy和客户端式架构有何区别呢?各自有什么优缺点呢?其实看一张图便可知晓。  proxy模式的话我们的select和update语句都是发送给代理,由这个代理来操作具体的底层数据库。所以必须要求代理本身需要保证高可用,否则数据库没有宕机,proxy挂了,那就走远了。  客户端模式通常在连接池上做了一层封装,内部与不同的库连接,sql交给smart-client进行处理。通常仅支持一种语言,如果其他语言要使用,需要开发多语言客户端。  各自的优缺点如下:3.3 内部文件  找了一个分库分表+分区的例子,基本上和分区表的差不多,只是多了多了很多表的.ibd文件,上面有文件的解释:\[miaojiaxing@Grim testmydata\]# ls | grep 'base\_info' base\_info\_00.frm base\_info\_00#P#p\_2018.ibd base\_info\_00#P#p\_2019.ibd base\_info\_00#P#p\_2020.ibd base\_info\_00#P#p\_2021.ibd base\_info\_00#P#p\_init.ibd base\_info\_00#P#p\_max.ibd base\_info\_01.frm base\_info\_01#P#p\_2018.ibd base\_info\_01#P#p\_2019.ibd base\_info\_01#P#p\_2020.ibd base\_info\_01#P#p\_2021.ibd base\_info\_01#P#p\_init.ibd base\_info\_01#P#p\_max.ibd base\_info.frm base\_info.ibd3.4 问题3.4.1 事务问题  既然分库分表了,那么肯定涉及到分布式事务,如何保证插入到不同库的多条记录能够要么同时成功,要么同时失败。有些同学可能想到XA,XA性能差而且不需要使用mysql5.7。柔性事务是目前主流的方案,TCC模式就属于柔性事务。  对于分布式事务问题每家公司有自己的实现,华为用saga,阿里用TXC,蚂蚁用DTX,支持FMT模式和TCC模式。3.4.2 join问题  tddl、MyCAT等都支持跨分片join。但是尽力避免跨库join,比如通过字段冗余的方式等。  如果出现了这种情况且中间件支持分片join,那么可以这样使用。如果不支持可以手工查询。四.总结  分表和在用途上不一样,分表是为了承接超大规模的表,单机放不下那种。分区的话则一般都是放在单机里的,用的比较多的是时间范围分区,方便归档。性能稳定上的话都是一个个子表,差不多,区别应该是分区表是mysql内部实现的,会比分表方案少一点数据交互本文转自 https://blog.csdn.net/li1669852599/article/details/109032879
  • [其他] MySQL索引优化20招
    索引优化规则1、like语句的前导模糊查询不能使用索引select * from doc where title like '%XX';   --不能使用索引 select * from doc where title like 'XX%';   --非前导模糊查询,可以使用索引因为页面搜索严禁左模糊或者全模糊,如果需要可以使用搜索引擎来解决。2、union、in、or 都能够命中索引,建议使用 inunion能够命中索引,并且MySQL 耗费的 CPU 最少。select * from doc where status=1 union all select * from doc where status=2;in能够命中索引,查询优化耗费的 CPU 比 union all 多,但可以忽略不计,一般情况下建议使用 in。select * from doc where status in (1, 2);or 新版的 MySQL 能够命中索引,查询优化耗费的 CPU 比 in多,不建议频繁用or。select * from doc where status = 1 or status = 2补充:有些地方说在where条件中使用or,索引会失效,造成全表扫描,这是个误区:①要求where子句使用的所有字段,都必须建立索引;②如果数据量太少,mysql制定执行计划时发现全表扫描比索引查找更快,所以会不使用索引;③确保mysql版本5.0以上,且查询优化器开启了index_merge_union=on, 也就是变量optimizer_switch里存在index_merge_union且为on。3、负向条件查询不能使用索引负向条件有:!=、<>、not in、not exists、not like 等。例如下面SQL语句:select * from doc where status != 1 and status != 2;可以优化为 in 查询:select * from doc where status in (0,3,4);4、联合索引最左前缀原则如果在(a,b,c)三个字段上建立联合索引,那么他会自动建立 a| (a,b) | (a,b,c)组索引。登录业务需求,SQL语句如下:select uid, login_time from user where login_name=? andpasswd=?可以建立(login_name, passwd)的联合索引。因为业务上几乎没有passwd 的单条件查询需求,而有很多login_name 的单条件查询需求,所以可以建立(login_name, passwd)的联合索引,而不是(passwd, login_name)。建立联合索引的时候,区分度最高的字段在最左边存在非等号和等号混合判断条件时,在建立索引时,把等号条件的列前置。如 where a>? and b=?,那么即使a 的区分度更高,也必须把 b 放在索引的最前列。最左前缀查询时,并不是指SQL语句的where顺序要和联合索引一致。下面的 SQL 语句也可以命中 (login_name, passwd) 这个联合索引:select uid, login_time from user where passwd=? andlogin_name=?但还是建议 where 后的顺序和联合索引一致,养成好习惯。假如index(a,b,c), where a=3 and b like 'abc%' and c=4,a能用,b能用,c不能用。5、不能使用索引中范围条件右边的列(范围列可以用到索引),范围列之后列的索引全失效范围条件有:<、<=、>、>=、between等。索引最多用于一个范围列,如果查询条件中有两个范围列则无法全用到索引。假如有联合索引 (empno、title、fromdate),那么下面的 SQL 中 emp_no 可以用到索引,而title 和 from_date 则使用不到索引。select * from employees.titles where emp_no < 10010' and title='Senior Engineer'and from_date between '1986-01-01' and '1986-12-31'6、不要在索引列上面做任何操作(计算、函数),否则会导致索引失效而转向全表扫描例如下面的 SQL 语句,即使 date 上建立了索引,也会全表扫描:select * from doc where YEAR(create_time) <= '2016';可优化为值计算,如下:select * from doc where create_time <= '2016-01-01';比如下面的 SQL 语句:select * from order where date < = CURDATE();可以优化为:select * from order where date < = '2018-01-2412:00:00';7、强制类型转换会全表扫描字符串类型不加单引号会导致索引失效,因为mysql会自己做类型转换,相当于在索引列上进行了操作。如果 phone 字段是 varchar 类型,则下面的 SQL 不能命中索引。select * from user where phone=13800001234可以优化为:select * from user where phone='13800001234';8、更新十分频繁、数据区分度不高的列不宜建立索引更新会变更 B+ 树,更新频繁的字段建立索引会大大降低数据库性能。“性别”这种区分度不大的属性,建立索引是没有什么意义的,不能有效过滤数据,性能与全表扫描类似。一般区分度在80%以上的时候就可以建立索引,区分度可以使用 count(distinct(列名))/count(*) 来计算。9、利用覆盖索引来进行查询操作,避免回表,减少select * 的使用覆盖索引:查询的列和所建立的索引的列个数相同,字段相同。被查询的列,数据能从索引中取得,而不用通过行定位符 row-locator 再到 row 上获取,即“被查询列要被所建的索引覆盖”,这能够加速查询速度。例如登录业务需求,SQL语句如下。Select uid, login_time from user where login_name=? and passwd=?可以建立(login_name, passwd, login_time)的联合索引,由于 login_time 已经建立在索引中了,被查询的 uid 和 login_time 就不用去 row 上获取数据了,从而加速查询。10、索引不会包含有NULL值的列只要列中包含有NULL值都将不会被包含在索引中,复合索引中只要有一列含有NULL值,那么这一列对于此复合索引就是无效的。所以我们在数据库设计时,尽量使用not null 约束以及默认值。11、is null, is not null无法使用索引12、如果有order by、group by的场景,请注意利用索引的有序性order by 最后的字段是组合索引的一部分,并且放在索引组合顺序的最后,避免出现file_sort 的情况,影响查询性能。例如对于语句 where a=? and b=? order by c,可以建立联合索引(a,b,c)。如果索引中有范围查找,那么索引有序性无法利用,如WHERE a>10 ORDER BY b;,索引(a,b)无法排序。13、使用短索引(前缀索引)对列进行索引,如果可能应该指定一个前缀长度。例如,如果有一个CHAR(255)的列,如果该列在前10个或20个字符内,可以做到既使得前缀索引的区分度接近全列索引,那么就不要对整个列进行索引。因为短索引不仅可以提高查询速度而且可以节省磁盘空间和I/O操作,减少索引文件的维护开销。可以使用count(distinct leftIndex(列名, 索引长度))/count(*) 来计算前缀索引的区分度。但缺点是不能用于 ORDER BY 和 GROUP BY 操作,也不能用于覆盖索引。不过很多时候没必要对全字段建立索引,根据实际文本区分度决定索引长度即可。14、利用延迟关联或者子查询优化超多分页场景MySQL 并不是跳过 offset 行,而是取 offset+N 行,然后返回放弃前 offset 行,返回 N 行,那当 offset 特别大的时候,效率就非常的低下,要么控制返回的总页数,要么对超过特定阈值的页数进行 SQL 改写。示例如下,先快速定位需要获取的id段,然后再关联:selecta.* from 表1 a,(select id from 表1 where 条件 limit100000,20 ) b where a.id=b.id;15、如果明确知道只有一条结果返回,limit 1 能够提高效率比如如下 SQL 语句:select * from user where login_name=?;可以优化为:select * from user where login_name=? limit 1自己明确知道只有一条结果,但数据库并不知道,明确告诉它,让它主动停止游标移动。16、超过三个表最好不要 join需要 join 的字段,数据类型必须一致,多表关联查询时,保证被关联的字段需要有索引。例如:left join是由左边决定的,左边的数据一定都有,所以右边是我们的关键点,建立索引要建右边的。当然如果索引在左边,可以用right join。17、单表索引建议控制在5个以内18、SQL 性能优化 explain 中的 type:至少要达到 range 级别,要求是 ref 级别,如果可以是 consts 最好consts:单表中最多只有一个匹配行(主键或者唯一索引),在优化阶段即可读取到数据。ref:使用普通的索引(Normal Index)。range:对索引进行范围检索。当 type=index 时,索引物理文件全扫,速度非常慢。19、业务上具有唯一特性的字段,即使是多个字段的组合,也必须建成唯一索引不要以为唯一索引影响了 insert 速度,这个速度损耗可以忽略,但提高查找速度是明显的。另外,即使在应用层做了非常完善的校验控制,只要没有唯一索引,根据墨菲定律,必然有脏数据产生。20.创建索引时避免以下错误观念索引越多越好,认为需要一个查询就建一个索引。宁缺勿滥,认为索引会消耗空间、严重拖慢更新和新增速度。抵制惟一索引,认为业务的惟一性一律需要在应用层通过“先查后插”方式解决。过早优化,在不了解系统的情况下就开始优化。索引选择性与前缀索引既然索引可以加快查询速度,那么是不是只要是查询语句需要,就建上索引?答案是否定的。因为索引虽然加快了查询速度,但索引也是有代价的:索引文件本身要消耗存储空间,同时索引会加重插入、删除和修改记录时的负担,另外,MySQL在运行时也要消耗资源维护索引,因此索引并不是越多越好。一般两种情况下不建议建索引。第一种情况是表记录比较少,例如一两千条甚至只有几百条记录的表,没必要建索引,让查询做全表扫描就好了。至于多少条记录才算多,这个个人有个人的看法,我个人的经验是以2000作为分界线,记录数不超过 2000可以考虑不建索引,超过2000条可以酌情考虑索引。另一种不建议建索引的情况是索引的选择性较低。所谓索引的选择性(Selectivity),是指不重复的索引值(也叫基数,Cardinality)与表记录数(#T)的比值:Index Selectivity = Cardinality / #T显然选择性的取值范围为(0, 1]``,选择性越高的索引价值越大,这是由B+Tree的性质决定的。例如,employees.titles表,如果title`字段经常被单独查询,是否需要建索引,我们看一下它的选择性:SELECT count(DISTINCT(title))/count(*) AS Selectivity FROM employees.titles; +-------------+ | Selectivity | +-------------+ |      0.0000 | +-------------+title的选择性不足0.0001(精确值为0.00001579),所以实在没有什么必要为其单独建索引。有一种与索引选择性有关的索引优化策略叫做前缀索引,就是用列的前缀代替整个列作为索引key,当前缀长度合适时,可以做到既使得前缀索引的选择性接近全列索引,同时因为索引key变短而减少了索引文件的大小和维护开销。下面以employees.employees表为例介绍前缀索引的选择和使用。假设employees表只有一个索引<emp_no>,那么如果我们想按名字搜索一个人,就只能全表扫描了:EXPLAIN SELECT * FROM employees.employees WHERE first_name='Eric' AND last_name='Anido'; +----+-------------+-----------+------+---------------+------+---------+------+--------+-------------+ | id | select_type | table     | type | possible_keys | key  | key_len | ref  | rows   | Extra       | +----+-------------+-----------+------+---------------+------+---------+------+--------+-------------+ |  1 | SIMPLE      | employees | ALL  | NULL          | NULL | NULL    | NULL | 300024 | Using where | +----+-------------+-----------+------+---------------+------+---------+------+--------+-------------+如果频繁按名字搜索员工,这样显然效率很低,因此我们可以考虑建索引。有两种选择,建<first_name>或<first_name, last_name>,看下两个索引的选择性:SELECT count(DISTINCT(first_name))/count(*) AS Selectivity FROM employees.employees; +-------------+ | Selectivity | +-------------+ |      0.0042 | +-------------+ SELECT count(DISTINCT(concat(first_name, last_name)))/count(*) AS Selectivity FROM employees.employees; +-------------+ | Selectivity | +-------------+ |      0.9313 | +-------------+<first_name>显然选择性太低,``<first_name, last_name>选择性很好,但是first_name和last_name加起来长度为30,有没有兼顾长度和选择性的办法?可以考虑用first_name和last_name的前几个字符建立索引,例如<first_name, left(last_name, 3)>`,看看其选择性:SELECT count(DISTINCT(concat(first_name, left(last_name, 3))))/count(*) AS Selectivity FROM employees.employees; +-------------+ | Selectivity | +-------------+ |      0.7879 | +-------------+ 选择性还不错,但离0.9313还是有点距离,那么把last_name前缀加到4:SELECT count(DISTINCT(concat(first_name, left(last_name, 4))))/count(*) AS Selectivity FROM employees.employees; +-------------+ | Selectivity | +-------------+ |      0.9007 | +-------------+这时选择性已经很理想了,而这个索引的长度只有18,比<first_name, last_name>短了接近一半,我们把这个前缀索引建上:ALTER TABLE employees.employees ADD INDEX `first_name_last_name4` (first_name, last_name(4));此时再执行一遍按名字查询,比较分析一下与建索引前的结果:SHOW PROFILES; +----------+------------+---------------------------------------------------------------------------------+ | Query_ID | Duration   | Query                                                                           | +----------+------------+---------------------------------------------------------------------------------+ |       87 | 0.11941700 | SELECT * FROM employees.employees WHERE first_name='Eric' AND last_name='Anido' | |       90 | 0.00092400 | SELECT * FROM employees.employees WHERE first_name='Eric' AND last_name='Anido' | +----------+------------+---------------------------------------------------------------------------------+性能的提升是显著的,查询速度提高了120多倍。前缀索引兼顾索引大小和查询速度,但是其缺点是不能用于ORDER BY和GROUP BY操作,也不能用于Covering index(即当索引本身包含查询所需全部数据时,不再访问数据文件本身)。 转自:https://mp.weixin.qq.com/s/hoewqvinJI91UFvbkNUyqQ
总条数:1406 到第
上滑加载中