本文主要總結關于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.pswp.cn/news/282440.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/282440.shtml
英文地址,請注明出處:http://en.pswp.cn/news/282440.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

CS Academy Gcd Rebuild

題目鏈接:https://csacademy.com/contest/archive/task/gcd-rebuild/statement/ 題目大意:給出一個N*M的矩陣,其中第i行j列表示gcd(a[i], b[j]),現在不知道數組a,b,給出這個矩陣,求a&#xff0c…

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部…

2018-08-15期 HBase命令行使用案例

1、進入hbase命令行[roothadoop-server01 bin]# hbase shell2、命令行幫助COMMAND GROUPS:Group name: generalCommands: status, table_help, version, whoamiGroup name: ddlCommands: alter, alter_async, alter_status, create, describe, disable, disable_all, drop, dro…

面向對象五大設計原則

最近在看七牛云許式偉的架構課, 重溫了面向對象五大設計原則(SOLID),扣理論文字找出處。(當然許老板是不可能深聊這么低級的內容,🤡)注意區分設計原則和設計模式。設計原則更為抽象和泛化;設計模式也是抽象…

python函數式編程-匿名函數

>>> map(lambda x: x * x, [1, 2, 3, 4, 5, 6, 7, 8, 9]) [1, 4, 9, 16, 25, 36, 49, 64, 81] 關鍵字lambda表示匿名函數,冒號前面的x表示函數參數。 匿名函數有個限制,就是只能有一個表達式,不用寫return,返回值就是該表…

bean初始化、注銷

關于在spring 容器初始化 bean 和銷毀前所做的操作定義方式有三種: 第一種:通過PostConstruct 和 PreDestroy 方法 實現初始化和銷毀bean之前進行的操作 第二種是:通過 在xml中定義init-method 和 destory-method方法 第三種是:…

谷歌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…

js獲取屏幕寬高和下拉加載更多

document.body.clientWidth > BODY對象寬度 document.body.clientHeight > BODY對象高度 document.documentElement.clientWidth > 可見區域寬度 document.documentElement.clientHeight > 可見區域高度 網頁可見區域寬: document.body.clientWid…

X5開發中buttongrounp對應contents組件切換時速度快點無效

官方提供的解決辦法是:http://docs.wex5.com/wex5-ui-question-list-2084/ 原文如下:【問題】buttongrounp中的button按鈕全是代碼動態生成,對應的contents中的content也是代碼動態生成。發現在快讀點擊button的時候,content就會死…

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…

MAVEN簡介之——settings.xml

概述 Maven的settings.xml配置了Maven執行的方式,像pom.xml一樣,但是它是一個通用的配置,不能綁定到任何特殊的項目。它通常包括本地倉庫地址,遠程倉庫服務,認證信息等。 settings.xml存在于兩個位置: mave…

裝win10系統

一、使用U盤介質安裝win10系統(官方方式) 官方安裝工具下載地址:https://www.microsoft.com/zh-cn/software-download/windows10 1、進入官方安裝工具下載頁面,點擊立即下載工具,下載安裝工具。2、下載完成后&#xff…