一切福田,不離方寸,從心而覓,感無不通。

Category Archives: MySQL

MySQL:创建高性能的索引

一、索引基础  定义 索引,也叫做“键(Key)”,是存储引擎用于快速查找记录的一种数据结构。索引对于良好的性能非常关键,索引是对查询性能优化最有效的手段。 索引类型 1.B-Tree索引 当人们谈论索引的时候,如果没有特别指明类型,那多半说的是B-Tree索引,它使用B-Tree数据结构来存储数据。B-Tree通常意味着所有的值是按顺序存储的,并且每一个叶子节点到根的距离相同。 B-Tree索引的几个匹配原则: a.全值匹配:和索引中的所有列进行匹配。 b.匹配最左前缀:即索引的第一列。 c.匹配列前缀:即只匹配某一列的值的开头部分。 d.匹配范围值。 e.精确匹配某一列并范围匹配另外一列。 f.只访问索引的查询,即:覆盖索引。   B-Tree索引的几个限制(索引失效): a.不是按照索引的最左列开始查找,则不能使用索引。 b.不能跳过索引中的列。 c.如果查询中有某个列的范围查询,则其右边所有列都无法使用索引。   2.哈希索引 哈希索引(hash index)基于哈希表实现,只有精确匹配索引所有列的查询才有效。在MySQL中只有Memory引擎显式支持哈希索引。我们在这里只作了解。   3.R-Tree索引 R-Tree索引(空间数据索引),可以用作地理数据存储。MySQL中目前仅MyISAM引擎支持。与B-Tree不同,此类型的索引无须前缀查询。必须使用MySQL的GIS相关函数来维护数据,但遗憾的是MySQL的GIS支持并不完善。   4.全文索引 全文索引是一种特殊类型的索引,它查找的是文本中关键词,而不是直接比较索引中的值。全文索引更类似于搜索引擎做的事情,而不是简单的WHERE条件匹配。   二、索引的优点 优点: 1.索引大大减少了服务器需要扫描的数据量。 2.索引可以帮助服务器避免排序和临时表。 3.索引可以将随机I/O变为顺序I/O。   什么样的表需要使用索引?简单的说应该遵循以下3条准则: 1.非常小的表:全表扫描更高效。 2.中到大型表:索引非常有效。 3.特大型的表:创建和使用索引的代价非常高。如果表有大量插入和更新,更新索引将是很大的一个开销。对于特大表,建议使用表分区技术,分区后再使用索引。   三、高性能的索引策略 示例以【居民表:resident】为例,以下是此表的结构: 1.独立的列 独立的列是指索引列不能是表达式的一部分,也不能是函数的参数。 反例:   2.前缀索引和索引选择性 前缀索引:如果需要索引的字符列很长,这会让索引变得大且慢。通常可以只索引此列开始的部分字符。这样可以大大节约索引空间,从而提高索引效率。 索引选择性:是指不重复的索引值和数据表的记录总数的比值。此值越高,索引效率越高。例如:唯一索引和主键的索引选择性是1,性能也是最好的。 索引选择性是创建前缀索引依据。 例子:给列RESIDENT_NAME加索引,varchar(500)显然太长了,我们用前缀做索引。 先计算完整列的选择性:0.4867 再计算最接近的前缀选择性,可以看到15个字符后,20个字符也是0.4867,因此15个字符作为前缀是最合适的。 最后创建索引:   3.多列索引 很多人对多列索引的理解都不够。一个常见的错误是:为每个列都创建独立的索引;另一个是按照错误的顺序创建多列索引。 反例:独立索引对多条件查询的性能提升是很小的,一般只能匹配到一个索引,效率肯定要大打折扣的。 正例:创建一个多列索引,扫描的行数马上降了下来,快了十几倍,这还只是个简单的示例。   4.选择合适的列顺序 最让人困惑的问题莫过于索引列的顺序,正确的顺序依赖于使用该索引的查询。也要考虑到排序和分组的需要。 例子:是什么让我决定以SP_ID在前创建了上面的多列索引:SP_ID_GENDER_CODE ? 答案是:计算各列的选择性。   5.聚簇索引 聚簇索引并不是一种单独的索引类型,而是一种数据存储方式。InnoDB的聚簇索引实际上在同一个结构中保存了B-Tree索引和数据行。主键就是一个典型的聚簇索引。   6.覆盖索引 如果一个索引包含要查询的所有字段,不需要再去表里读取数据,这样的索引就叫做覆盖索引。覆盖索引能极大的提高查询性能。 例子:把查询中需要的字段改为索引中的字段时,这样一个覆盖索引就形成了。索引也只匹配到多列索引,ref也变为了常数。Extra也显示了Using index。   7.用索引做排序 可以用同一个索引既满足排序,又用于查询。这样的索引是最优的,历为我们日常工作中遇到查询一般都是要排序的。这里有个限制:如果查询涉及到多表联合,排序用的字段必须全部是第一个表的,才能使用索引做排序。 例子:   8.冗余和重复索引 重复索引:是指在相同的列上按照相同的顺序创建的相同类型的索引。避免出现这样的情况,发现要删除。 冗余索引:是指一个或多个列同步出现在多个索引中,各索引的列数、顺序不同。冗余索引也应避免。但有时查询写的不合理,可能出现单独为优化某个查询出现的冗余索引。 P.S 创建冗余索引时可能影响其他索引的匹配,从而导致以前的查询性能降低。   四、索引案例 索引 index(a, b, […]

龙生   22 Aug 2021
View Details

如何查询mysql数据库大小

要想知道每个数据库的大小的话,步骤如下: 1、进入information_schema 数据库(存放了其他的数据库的信息) use information_schema; 2、查询所有数据的大小: select concat(round(sum(data_length/1024/1024),2),’MB') as data from tables; 3、查看指定数据库的大小: 比如查看数据库home的大小 select concat(round(sum(data_length/1024/1024),2),’MB') as data from tables where table_schema=’home'; 4、查看指定数据库的某个表的大小 比如查看数据库home中 members 表的大小 select concat(round(sum(data_length/1024/1024),2),’MB') as data from tables where table_schema=’home' and table_name=’members';   from:https://blog.csdn.net/weixin_34050389/article/details/89826749

龙生   18 Aug 2021
View Details

MySQL事务与MVCC如何实现的隔离级别

前言 其实数据库章节基本上的知识点我都写过一遍了,包括这篇事务和MVCC的,但是国庆期间我翻阅资料的时候我发现之前写的还差点意思,例子举得也差点意思,那我就根据我自己最新的理解,加上之前的总结相当于重写了,希望你也有新的收获。   数据库事务介绍   事务的四大特性(ACID) 原子性(atomicity): 事务的最小工作单元,要么全成功,要么全失败。 一致性(consistency): 事务开始和结束后,数据库的完整性不会被破坏。 隔离性(isolation): 不同事务之间互不影响,四种隔离级别为RU(读未提交)、RC(读已提交)、RR(可重复读)、SERIALIZABLE (串行化)。 持久性(durability): 事务提交后,对数据的修改是永久性的,即使系统故障也不会丢失。   事务的隔离级别   读未提交(Read UnCommitted/RU) 又称为脏读,一个事务可以读取到另一个事务未提交的数据。这种隔离级别岁最不安全的一种,因为未提交的事务是存在回滚的情况。   读已提交(Read Committed/RC) 又称为不可重复读,一个事务因为读取到另一个事务已提交的修改数据,导致在当前事务的不同时间读取同一条数据获取的结果不一致。 举个例子,在下面的例子中就会发现SessionA在一个事务期间两次查询的数据不一样。原因就是在于当前隔离级别为 RC,SessionA的事务可以读取到SessionB提交的最新数据。 发生时间 SessionA SessionB 1 begin; 2 select * from user where id=1;(张三) 3 update user set name=’李四' where id=1;(默认隐式提交事务) 4 select * from user where id=1;(李四) 5 update user set name=’王二' where id=1;(默认隐式提交事务) 6 select * from user where id=1;(王二)   可重复读(Repeatable Read/RR) 又称为幻读,一个事物读可以读取到其他事务提交的数据,但是在RR隔离级别下,当前读取此条数据只可读取一次,在当前事务中,不论读取多少次,数据任然是第一次读取的值,不会因为在第一次读取之后,其他事务再修改提交此数据而产生改变。因此也成为幻读,因为读出来的数据并不一定就是最新的数据。 举个例子:在SessionA中第一次读取数据时,后续其他事务修改提交数据,不会再影响到SessionA读取的数据值。此为可重复读。 发生时间 SessionA SessionB 1 begin; 2 select * from user where id=1;(张三) 3 update user set […]

龙生   12 Aug 2021
View Details

MySQL自定义函数:身份证号15位转18位

 

龙生   06 Aug 2021
View Details

【mysql】 1292. Truncated incorrect INTEGER value: "

错误分析 一般来讲,找到对应的insert字段,然后看一下是否是由于字段类型不匹配导致的。 例如,表中声明的是bigInt类型,你传值传了个字符串进入。 另外,如果你是通过insert into select的方式,将查询结果导入到新的表中,可能你单独执行select中的内容,是可以查询到相应的结果,但是当你执行insert into语句时,会产生如下错误

在MySQL的论坛上找到一个哥们儿说的内容,也就是说这个1292的错误,有可能并不是错误,而是警告提示。可以通过ignore关键字进行警告屏蔽 所以,我把自己的代码前缀,改成如下格式,即可正常执行导入操作

  ———————————————— 版权声明:本文为CSDN博主「小魏的马仔」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/xuexiiphone/article/details/103426404

龙生   30 Jul 2021
View Details

MySQL处理JSON数组,数组转字符串

GROUP_CONCAT:group_concat( [distinct] 要连接的字段 [order by 排序字段 asc/desc  ] [separator '分隔符'] ) SUBSTRING_INDEX:substring_index(str,delim,count) str:要处理的字符串 delim:分隔符 count:计数 SUBSTRING:SUBSTRING(string,position) JSON_EXTRACT:取json字符串字段下的某个键的值

龙生   29 Jul 2021
View Details

必须知道的SQL语句不走索引时的排查利器

前言: 在索引优化时,经常会看到的一句话:如果索引字段出现隐式字符集转换的话,那么索引将失效,进而转为全表扫描,查询效率将大大降低,要避免出现隐式字符集转换; 在此我想问问同学们: 大家知道为什么隐式字符集转换会导致索引失效吗? 实际场景中有没有遇到过隐式字符集转换导致索引失效的场景,具体排查的过程; 本文主线: 由上面的两个问题牵引出了本文的主线; 简单描述下隐式字符集转换导致索引失效的原因 然后模拟实际场景排查隐式字符集转换导致索引失效的过程 隐式字符集转换导致索引失效的原因 MySQL索引的数据结构是 B+Tree,想要走索引查询必须要满足其 最左前缀原则 ,否则无法通过索引树进行查找,只能进行全表扫描; 例如:下面的这个SQL由于在 索引字段 上使用函数进行运算,导致索引失效

  上面的这个SQL怎么改造才能使索引生效呢?如下所示:

  通过上面的小例子可以知道,如果在索引字段上使用函数运算,则会导致索引失效,而索引字段的 隐式字符集转换 由于MySQL会自动的在索引字段上加上 转换函数 ,进而会导致索引失效; 那接下来我们就通过模拟的实际场景来具体看看是不是由于MySQL自动给加上了转换函数而导致索引失效的; 模拟场景 + 问题排查 由于导致索引失效的原因有很多,如果自己写的SQL怎么看都没问题,但是通过查看执行计划发现就是没有走索引查询,此时就会让很多人陷入困境,这到底是怎么导致的呢? 此时本文重点将要讲述的工具就要闪亮登场啦: explain extended + show warnings ; 使用这个工具可以将执行的SQL语句的一些扩展信息展示出来,这些扩展信息就包括:MySQL优化时可能会添加上字符集转换函数,使得字符集不匹配的SQL可以正确执行下去; 下面就来具体聊聊 explain extended + show warnings 的使用; 模拟隐式字符集转换的场景: 首先创建两个字符集不一样的表:

  然后使用存储过程构造数据:

  注意:在构造数据时,记得将 t_employees 表中的 de_no 字段值构造的 离散些 ,因为如果索引字段值的 区分度很低 的话,那么MyQSL优化器通过采样统计分析时,发现索引查询和全表扫描性能差不多,就会直接进行全表扫描了; 索引失效的查询SQL语句: 将表和数据构造完后,我们使用SQL语句进行查询下,然后再看看其执行计划;

  其执行计划如下: 发现 t_employees 表中的 de_no 字段有索引,但是没有走索引查询,type=ALL 走的全表扫描,但是通过查看SQL语句发现其没有问题呀,表面看上去都是满足走索引查询的条件呀,排查到这发现遇到了困境,苦恼啊! 还好,通过在网络世界上遨游,最终发现了 explain extended + show warnings 利器,利用它快速发现了索引失效的根本原因,然后快速找到了解决方案; 下面就来聊聊这个利器的具体使用,开森! 使用利器快速排查问题: 注意:explain 后面跟的关键字 EXTENDED(扩展信息) 在MySQL5.7及之后的版本中废弃了,但是该语法仍被识别为向后兼容,所以在5.7版本及后续版本中,可以不用在 explain 后面添加 EXTENDED 了; EXTENDED关键字的具体查阅资料:https://dev.mysql.com/doc/refman/5.7/en/explain-extended.html 具体使用方法如下: ①、首先在MySQL的可视化工具中打开一个 命令列介面 :工具 --> 命令列介面 ②、然后输入下面的SQL并按回车:

  ③、然后紧接着输入命令 show warnings; 并回车,会出现如下图所示内容: 通过展示出的执行SQL扩展信息,发现MySQL在字符集不一致时自动添加上字符集转换函数,因为是在 索引字段 de_no 上添加的转换函数,所以就导致了索引失效; 而如果我们没看扩展信息的话,那么可能直到我们查看表结构的时候才会发现是由于字符集不一致导致的,这样就会花费很多的时间; 扩展:隐式类型转换 咱们聊完上面的隐式字符集转换导致索引失效的情况,再来简单聊聊另一种 隐式类型转换 导致索引失效的情况; […]

龙生   09 Jul 2021
View Details

大批量更新数据mysql批量更新的四种方法

mysql 批量更新如果一条条去更新效率是相当的慢, 循环一条一条的更新记录,一条记录update一次,这样性能很差,也很容易造成阻塞。 mysql 批量更新共有以下四种办法 1、.replace into 批量更新

  2、insert into …on duplicate key update批量更新

  3.创建临时表,先更新临时表,然后从临时表中update

  注意:这种方法需要用户有temporary 表的create 权限。 4、使用mysql 自带的语句构建批量更新 mysql 实现批量 可以用点小技巧来实现:

  这句sql 的意思是,更新orderId 字段,如果id=1 则orderId 的值为3,如果id=2 则orderId 的值为4…… where部分不影响代码的执行,但是会提高sql执行的效率。确保sql语句仅执行需要修改的行数,这里只有3条数据进行更新,而where子句确保只有3行数据执行。 如果更新多个值的话,只需要稍加修改:

  到这里,已经完成一条mysql语句更新多条记录了。 php中用数组形式赋值批量更新的代码:

  这个例子,有8条记录进行更新。代码也很容易理解,你学会了吗 更新 100000条数据的性能就测试结果来看,测试当时使用replace into性能较好。 replace into 和 insert into on duplicate key update的不同在于: replace into 操作本质是对重复的记录先delete 后insert,如果更新的字段不全会将缺失的字段置为缺省值,用这个要悠着点否则不小心清空大量数据可不是闹着玩的。 insert into 则是只update重复记录,不会改变其它字段。   from:https://www.cnblogs.com/mslagee/p/6509682.html

龙生   30 Jun 2021
View Details

MySQLHelper/Util类

 

龙生   30 Jun 2021
View Details

mysql强制使用指定索引查询

语法: select * from table_name force index (index_name) where conditions; 使用 关键字 force

  from:https://www.cnblogs.com/pc-boke/articles/9916986.html

龙生   18 Jun 2021
View Details