本文主要总结关于mysql的优化(将会持续更新)

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

ON DUPLICATE KEY UPDATE

事件背景

在阅读公司原来代码的过程中,我发现了这样一段代码:

$sql = "INSERT INTO {$table} ({$fields}) VALUES " . $values;
if (!empty($onDuplicate)) {$sql .= ' ON DUPLICATE KEY UPDATE '. $onDuplicate;
}

在语义的理解上,应当是索引冲突则更新原有索引数据。经过查阅资料,我总结如下:

假设业务上我们需要的就是如果存在则更新,如果不存在则新增. INSERT 中ON DUPLICATE KEY UPDATE(用redis的kv就可以很容易的实现.在MySQL中也有这样的功能)

但是这个在在使用的时候需要把关键的字段(列)设置为key ,unique key。(也就是会发生冲突的索引)

INSERT 中ON DUPLICATE KEY UPDATE的使用:

如果您指定了ON DUPLICATE KEY UPDATE,并且插入行后会导致在一个UNIQUE索引或PRIMARY KEY中出现重复值,则执行旧行UPDATE。

栗子

CREATE TABLE `test_duplicate` (`id` int(11) NOT NULL AUTO_INCREMENT,`a` int(11) NOT NULL,`b` int(11) NOT NULL,`c` int(11) NOT NULL,PRIMARY KEY (`id`),UNIQUE KEY `a` (`a`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
insert into test_duplicate (a,b,c) values(1,2,3);

假设我们有表如上,SQL列a被定义为UNIQUE,并且包含值1,则以下两段语句具有相同的效果:

mysql>INSERT INTO test_duplicate (a,b,c) VALUES (1,2,3) ON DUPLICATE KEY UPDATE c=c+1;  
mysql> select * from test_duplicate;
+----+---+---+---+
| id | a | b | c |
+----+---+---+---+
|  1 | 1 | 2 | 4 |
+----+---+---+---+mysql>SELECT id,a,b,c from test_duplicate where a=1;
mysql>UPDATE table SET c=c+1 WHERE id=1; SELECT id,a,b,c from test_duplicate where a=1;
+----+---+---+---+
| id | a | b | c |
+----+---+---+---+
|  1 | 1 | 2 | 5 |
+----+---+---+---+

从结果可以看出来,2段SQL都都c进行了+1操作。但是insert实际上并没有进行插入数据而是进行了更新数据。

那如果,我们表内有两个可能会产生冲突的键时,又会如何呢?

mysql> ALTER TABLE `test_duplicate` ADD UNIQUE(`b`);
mysql> INSERT INTO test_duplicate (a,b,c) VALUES (2,3,4);mysql> INSERT INTO test_duplicate (a,b,c) VALUES (1,3,4) ON DUPLICATE KEY UPDATE c=c+1;
Query OK, 2 rows affected (0.00 sec)mysql> select * from test_duplicate;
+----+---+---+---+
| id | a | b | c |
+----+---+---+---+
|  1 | 1 | 2 | 6 |
|  3 | 2 | 3 | 4 |
+----+---+---+---+

可以看出来,同时更新了两条数据 。

那假如同一行数据,我们有两个冲突的值会产生怎么样的结果呢?

mysql> INSERT INTO test_duplicate (a,b,c) VALUES (1,2,4) ON DUPLICATE KEY UPDATE c=c+1;
mysql> select * from test_duplicate;
+----+---+---+---+
| id | a | b | c |
+----+---+---+---+
|  1 | 1 | 2 | 7 |
|  3 | 2 | 3 | 4 |
+----+---+---+---+

因此,我们在设计表的时候,应该尽量避免多冲突值得存在,如果实在避免不了,我们可以使用values方法获取本次提交的值。VALUES()函数只在INSERT...UPDATE语句中有意义,其它时候会返回NULL。

mysql> INSERT INTO test_duplicate (a,b,c) VALUES (1,2,4) ON DUPLICATE KEY UPDATE c=values(c);
mysql> select * from test_duplicate;
+----+---+---+---+
| id | a | b | c |
+----+---+---+---+
|  1 | 1 | 2 | 4 |
|  3 | 2 | 3 | 4 |
+----+---+---+---+

应该一般需求都是要达到这个结果

需要注意的是,在事务中,只有SELECT ... FOR UPDATE 或LOCK IN SHARE MODE 同一笔数据时会等待其它事务结束后才执行,一般SELECT ... 则不受此影响。拿上面的实例来说,当我执行select status from t_goods where id=1 for update;后。我在另外的事务中如果再次执行select status from t_goods where id=1 for update;则第二个事务会一直等待第一个事务的提交,此时第二个查询处于阻塞的状态,但是如果我是在第二个事务中执行select status from t_goods where id=1;则能正常查询出数据,不会受第一个事务的影响。

关于老的数据库密码设置

刚入职的时候,我编译了自己的docker是php7环境的,然后无法支持mysql只支持mysqlnd作为pdo驱动。于是乎,错误来了

"SQLSTATE[HY000] [2000] mysqlnd cannot connect to MySQL 4.1+ using the old insecure authentication. Please use an administration tool to reset your password with the command SET PASSWORD = PASSWORD('your_existing_password'). This will store a new, and more secure, hash value in mysql.user. If this user is used in other scripts executed by PHP 5.2 or earlier you might need to remove the old-passwords flag from your my.cnf file

在google遨游了很久,也没找到解决方式,然后,也尝试着装mysql然后编译PHP的时候使用mysql的头文件尝试修改mysqlnd的方式也没有成功。

网上大部分答案都需要登入mysql服务器去改my.cnf。

最后终于搞定了,将他记录下来,原来可以临时修改会话的密码长度然后重设。

mysql> SELECT user, Length(`Password`) FROM  `mysql`.`user`;
+----------------+--------------------+
| user           | Length(`Password`) |
+----------------+--------------------+
| root           |                 16 |
| root           |                  0 |
| root           |                  0 |
|                |                  0 |
|                |                  0 |
| root           |                 16 |
| test           |                 16 |
| club_star_user |                 16 |
| club_star_user |                 16 |
| wenlong11      |                 16 |
+----------------+--------------------+
mysql> SET SESSION old_passwords = 0;
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT @@global.old_passwords, @@session.old_passwords, Length(PASSWORD('abc'));
mysql> UPDATE mysql.user SET Password = PASSWORD('123456') WHERE user = 'xxxx';
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)mysql> SELECT user, Length(`Password`) FROM  `mysql`.`user`;
+----------------+--------------------+
| user           | Length(`Password`) |
+----------------+--------------------+
| root           |                 16 |
| root           |                  0 |
| root           |                  0 |
|                |                  0 |
|                |                  0 |
| root           |                 16 |
| test           |                 16 |
| club_star_user |                 16 |
| club_star_user |                 16 |
| wenlong11      |                 41 |
+----------------+--------------------+

可以观察到 密码长度终于变成41的新版的长度了

order by 排序不准

mysql排序 假如对很多值相等的值进行order 分页 会产生乱序 导致数据重复

select * from where a = 3 and b = 5 order by c descselect * from where a = 3 and b =5 order by c desc, d desc

解决方式: 1、尽量不要使用这种字段排序 2、如果业务需求,将其修改成多种混合 如 order field desc => order field desc, uniqueField desc 确保结果不会混乱

MySQL Explain

示例: explain select * from tablename;

将会得出结果查询详情,而不是结果集

expain出来的信息有10列,分别是id、select_type、table、type、possible_keys、key、key_len、ref、rows、Extra

force index

在某些情况下,mysql推荐的索引并不是我们最想用的业务(根据业务需求)

这个时候,我们可以将自己确定的索引进行设置,保证本条SQL强制走索引

select * from $table_name force index(index_name) where condition  limit number

测试性能比较

8000W 数据,不用force index 200s都未查询完毕

加了之后,1S左右完成

执行explain,发现这个sql扫描了8000W条记录到磁盘上。然后再进行筛选。type=index说明整个索引树都被扫描了,效果显然不理想。

ignore index

对应的,在某些情况下我们确定了不需要某个索引

这个时候,我们可以将此索引忽略,保证本条SQL不遍历这个索引

转载于:https://my.oschina.net/lwl1989/blog/1927713

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/282440.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ASP.NET Core 在 IIS 下的两种部署模式

KestrelServer最大的优势体现在它的跨平台的能力,如果ASP.NET CORE应用只需要部署在Windows环境下,IIS也是不错的选择。ASP.NET CORE应用针对IIS具有两种部署模式,它们都依赖于一个IIS针对ASP.NET CORE Core的扩展模块。一、ASP.NET CORE Cor…

navicat连接远程mysql

环境介绍: 这里,我连接的是阿里云的服务器,自己搭的环境,用的是mysql 5.7一 首先第一步,需要进入远程服务器的mysql,更改host访问权限 然后,将root允许访问的host 改为%(任何ip地址都可以访问) 注: 原来是只允许本地访问二 本地用navicat连接远程mysql 1. 常规部分填写2. SSH部…

面向对象五大设计原则

最近在看七牛云许式伟的架构课, 重温了面向对象五大设计原则(SOLID),扣理论文字找出处。(当然许老板是不可能深聊这么低级的内容,🤡)注意区分设计原则和设计模式。设计原则更为抽象和泛化;设计模式也是抽象…

谷歌F12调试公众号时,让鼠标显示出来

yi 环境介绍: win10 , 谷歌浏览器yii 概述: 在项目中,需要调试公众号,本地环境搭好之后,在谷歌浏览时,发现移动到公众号区域,鼠标居然不见了,这让我怎么操作?各种操作可谓是日了狗了,非常麻烦yiii 调试时鼠标不见的解决办法: 网上各种说法众说纷纭,这里,我给出本人认为最恰当简…

利用bootstrap插件设置时间

$("#"id_rand" .shijian-input").each(function () { $(this).datetimepicker({ lang:"ch", //语言选择中文 注:旧版本 新版方法:$.datetimepicker.setLocale(ch); format: "hh : ii", /…

C# 编写的 64位操作系统 -MOOS

MOOSMOOS ( My Own Operating System )是一个使用.NET Native AOT技术编译的C# 64位操作系统。项目地址:https://github.com/nifanfa/MOOS编译关于编译MOOS的信息,请阅读 编译维基页面:https://github.com/nifanfa/MOOS/wiki/。编译要求VMwar…

JAVA语言基础-面向对象(IO:IO字符流、递归)

2019独角兽企业重金招聘Python工程师标准>>> 21.01_IO流(字符流FileReader) 1.字符流是什么 字符流是可以直接读写字符的IO流字符流读取字符, 就要先读取到字节数据, 然后转为字符. 如果要写出字符, 需要把字符转为字节再写出.2.FileReader FileReader类的read()方法…

windows下, nginx 提示错误 No input file specified

一 环境介绍: win10, LNMP 二 错误描述: 访问网站时,提示"No input file specified"错误. 排错阶段: 1. 查看nginx access日志 (access.log) 发现提示404 错误 2. 分析原因: 这时,在同目录下创建一个txt文件,访问就可以正常输出了 这说明 现在nginx 访问php 没…

Ubuntu20.04+docker+jenkins+飞书实现自动化发布

一、从0-1一点一滴实现如何本地提交代码到gitlab然后实现前后端自动发布1.更新apt包索引sudo apt-get update2.安装必备的软件包以允许apt通过https使用存储库sudo apt-get install ca-certificates curl gnupg lsb-release3.添加Docker官方版本的GPG密钥sudo mkdir -p /etc/ap…

一个Demo让你掌握Android所有控件

一个Demo让你掌握Android所有控件 原文:一个Demo让你掌握Android所有控件本文是转载收藏,侵删,出处:"安卓巴士" 下面给出实现各个组件的源代码: 1.下拉框实现--Spinner [java] view plaincopyprint?package com.cellcom; import java.util.ArrayList;…

九妹带你走向 架构师

迈向系统架构师编者按:系统架构师是许多程序员的梦想职业。今天的你也许已经掌握了各种开发工具,并且能够使用各种平台进行开发,但作为一个架构师的要求,也许还有很长的道路。邢波涛先生在LAMP架构上的造诣,让我邀请他…

WPF 使用 DrawingContext 绘制温度计

WPF 使用 DrawingContext 绘制温度计控件名:Thermometer作者: WPFDevelopersOrg原文链接: https://github.com/WPFDevelopersOrg/WPFDevelopers框架使用大于等于.NET40;Visual Studio 2022;项目使用 MIT 开源许可协议&#xff…

装win10系统

一、使用U盘介质安装win10系统(官方方式) 官方安装工具下载地址:https://www.microsoft.com/zh-cn/software-download/windows10 1、进入官方安装工具下载页面,点击立即下载工具,下载安装工具。2、下载完成后&#xff…

C#构造函数、操作符重载以及自定义类型转换

构造器 构造器(构造函数)是将类型的实例初始化的特殊方法。构造器可分为实例构造器和类型构造器,本节将详细介绍有关内容。 实例构造器 顾名思义,实例构造器的作用就是对类型的实例进行初始化。如果类没有显示定义任何构造器&…

「Dotnet 工具箱」 自动生成并绑定 Https 证书

这里是 Dotnet 工具箱,定期分享 Dotnet 有趣,有用的工具,不要忘记关注。介绍LettuceEncrypt 是一个使用 C# 开发的免费的工具,它和证书颁发机构 (CA)集成,比如 Lets Encrypt,它使用了…

1115: 零起点学算法22——华氏摄氏温度转换

1115: 零起点学算法22——华氏摄氏温度转换 Time Limit: 1 Sec Memory Limit: 64 MB 64bit IO Format: %lldSubmitted: 3522 Accepted: 1456[Submit][Status][Web Board]Description 输入一个华氏温度,根据公式C(5/9)(F-32)计算对应的摄氏温度。 Input 输入一个…

Navicat Premium 12 的安装破解

Navicat 这款软件可以说 是数据库可视化操作的神器, 有绿色的 (最原始版本, 好像现在已经不维护了) , 有金色的 (改良收费版 ) , 还有彩色的 (最新版) , 这里 , 推荐使用彩色版 (也就是截止目前最新的版本 12.0.27). 操作的话, 感觉相比于小绿和小金有很大改进 , 很棒 , 在此给…

Vuejs——组件——slot内容分发

2019独角兽企业重金招聘Python工程师标准>>> ①概述: 简单来说,假如父组件需要在子组件内放一些DOM,那么这些DOM是显示、不显示、在哪个地方显示、如何显示,就是slot分发负责的活。 ②默认情况下 父组件在子组件内套的…

turtle库基础练习

画一组同切圆 import turtleturtle.shape(turtle)turtle.circle(10) turtle.circle(20) turtle.circle(30) turtle.circle(40) turtle.circle(50) turtle.circle(60) turtle.circle(70) turtle.circle(80)turtle.hideturtle() turtle.done() 画一组同心圆 import turtleturtle.…

检查你的项目的引用包依赖关系

2019独角兽企业重金招聘Python工程师标准>>> 随着着开发的进展,你的项目越来越大,引用的第三方包越来越多,但如何查看都依赖了哪些包,甚至传递依赖又是怎样? 首先解决这个问题的前提,你的项目需要是maven项目,然后可以做如下设置: 选中项目,右键->ru…