mysql第五天學習 Mysql全局優化總結

Mysql全局優化總結

在這里插入圖片描述

從上圖可以看出SQL及索引的優化效果是最好的,而且成本最低,所以工作中我們要在這塊花更多時間。

補充一點配置文件my.ini或my.cnf的全局參數:
假設服務器配置為:

  • CPU:32核
  • 內存:64G
  • DISK:2T SSD
    下面參數都是服務端參數,默認在配置文件的 [mysqld] 標簽下

mysql server系統參數

msyql server系統參數

max_connections=3000

連接的創建和銷毀都需要系統資源,比如內存、文件句柄,業務說的支持多少并發,指的是每秒請求數,也就是QPS。
一個連接最少占用內存是256K,最大是64M,如果一個連接的請求數據超過64MB(比如排序),就會申請臨時空間,放到硬盤上。
如果3000個用戶同時連上mysql,最小需要內存3000256KB=750M,最大需要內存300064MB=192G。
如果innodb_buffer_pool_size是40GB,給操作系統分配4G,給連接使用的最大內存不到20G,如果連接過多,使用的內存超過20G,將會產生磁盤SWAP,此時將會影響性能。連接數過高,不一定帶來吞吐量的提高,而且可能占用更多的系統資源。

max_user_connections=2980

允許用戶連接的最大數量,剩余連接數用作DBA管理。

back_log=300

MySQL能夠暫存的連接數量。如果MySQL的連接數達到max_connections時,新的請求將會被存在堆棧中,等待某一連接釋放資源,該堆棧數量即back_log,如果等待連接的數量超過back_log,將被拒絕。

wait_timeout=300

指的是app應用通過jdbc連接mysql進行操作完畢后,空閑300秒后斷開,默認是28800,單位秒,即8個小時。

interactive_timeout=300
指的是mysql client連接mysql進行操作完畢后,空閑300秒后斷開,默認是28800,單位秒,即8個小時。

sort_buffer_size=4M
每個需要排序的線程分配該大小的一個緩沖區。增加該值可以加速ORDER BY 或 GROUP BY操作。
sort_buffer_size是一個connection級的參數,在每個connection(session)第一次需要使用這個buffer的時候,一次性分配設置的內存。
sort_buffer_size:并不是越大越好,由于是connection級的參數,過大的設置+高并發可能會耗盡系統的內存資源。例如:500個連接將會消耗500*sort_buffer_size(4M)=2G。
join_buffer_size=4M
用于表關聯緩存的大小,和sort_buffer_size一樣,該參數對應的分配內存也是每個連接獨享。

innodb參數
innodb相關參數
https://dev.mysql.com/doc/refman/8.0/en/innodb-parameters.html#sysvar_innodb_buffer_pool_size
innodb_thread_concurrency=64
此參數用來設置innodb線程的并發數,默認值為0表示不被限制,若要設置則與服務器的CPU核心數相同或是CPU的核心數的2倍,如果超過配置并發數,則需要排隊,這個值不宜太大,不然可能會導致線程之間鎖爭用嚴重,影響性能。

innodb_buffer_pool_size=40G
innodb存儲引擎buffer pool緩存大小,一般為物理內存的60%-70%。
內存大小直接反應數據庫的性能。
在這里插入圖片描述

如何判斷當前數據庫的內存是否已經達到瓶頸了呢?
可以通過查看當前服務器的狀態,比較物理磁盤的讀取和內存讀取的比例來判斷緩沖池的命中率,通常InnoDB存儲引擎的緩沖池的命中率不應該小于99%,如:
mysql> show global status like ‘innodb%read%’\G;
當前服務器的狀態參數:

  • Innodb_buffer_pool_reads:表示從物理磁盤讀取頁的次數
  • Innodb_buffer_pool_read_ahead:預讀的次數
  • Innodb_buffer_pool_read_ahead_evicted:預讀的頁,但是沒有被讀取就從緩沖池中被替換的頁的數量,一般用來判斷預讀的效率
  • Innodb_buffer_pool_read_requests:從緩沖池中讀取頁的次數
  • Innodb_data_readsInnodb_rows_read:總共讀入的字節數
  • Innodb_data_reads:發起讀取請求的次數,每次讀取可能需要讀取多個頁
    以下公式可以計算各種對緩沖池的操作:

在這里插入圖片描述

innodb_lock_wait_timeout=10
行鎖鎖定時間,默認50s,根據公司業務定,沒有標準值。

innodb_flush_log_at_trx_commit=1

binlog參數
binlog相關參數
https://dev.mysql.com/doc/refman/8.0/en/replication-options-binary-log.html
sync_binlog=1

Mysql 8.0新特性詳解

建議使用8.0.17及之后的版本,更新的內容比較多。
參考文檔
添加棄用和刪除的特性:https://dev.mysql.com/doc/refman/8.0/en/mysql-nutshell.html
添加棄用和刪除的參數:https://dev.mysql.com/doc/refman/8.0/en/added-deprecated-removed.html
Mysql8 InnoDB架構:https://dev.mysql.com/doc/refman/8.0/en/innodb-architecture.html

1、新增降序索引
MySQL在語法上很早就已經支持降序索引,但實際上創建的仍然是升序索引,如下MySQL 5.7 所示,c2字段降序,但是從show create table看c2仍然是升序。8.0可以看到,c2字段降序。只有Innodb存儲引擎支持降序索引。

# ====MySQL 5.7演示====
mysql> create table t1(c1 int,c2 int,index idx_c1_c2(c1,c2 desc));
Query OK, 0 rows affected (0.04 sec)mysql> insert into t1 (c1,c2) values(1, 10),(2,50),(3,50),(4,100),(5,80);
Query OK, 5 rows affected (0.02 sec)mysql> show create table t1\G
*************************** 1. row ***************************Table: t1
Create Table: CREATE TABLE `t1` (`c1` int(11) DEFAULT NULL,`c2` int(11) DEFAULT NULL,KEY `idx_c1_c2` (`c1`,`c2`)    --注意這里,c2字段是升序
) ENGINE=InnoDB DEFAULT CHARSET=latin1
1 row in set (0.00 sec)mysql> explain select * from t1 order by c1,c2 desc;  --5.7也會使用索引,但是Extra字段里有filesort文件排序
+----+-------------+-------+------------+-------+---------------+-----------+---------+------+------+----------+-----------------------------+
| id | select_type | table | partitions | type  | possible_keys | key       | key_len | ref  | rows | filtered | Extra                       |
+----+-------------+-------+------------+-------+---------------+-----------+---------+------+------+----------+-----------------------------+
|  1 | SIMPLE      | t1    | NULL       | index | NULL          | idx_c1_c2 | 10      | NULL |    1 |   100.00 | Using index; Using filesort |
+----+-------------+-------+------------+-------+---------------+-----------+---------+------+------+----------+-----------------------------+
1 row in set, 1 warning (0.01 sec)# ====MySQL 8.0演示====
mysql> create table t1(c1 int,c2 int,index idx_c1_c2(c1,c2 desc));
Query OK, 0 rows affected (0.02 sec)mysql> insert into t1 (c1,c2) values(1, 10),(2,50),(3,50),(4,100),(5,80);
Query OK, 5 rows affected (0.02 sec)mysql> show create table t1\G
*************************** 1. row ***************************Table: t1
Create Table: CREATE TABLE `t1` (`c1` int DEFAULT NULL,`c2` int DEFAULT NULL,KEY `idx_c1_c2` (`c1`,`c2` DESC)  --注意這里的區別,降序索引生效了
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
1 row in set (0.00 sec)mysql> explain select * from t1 order by c1,c2 desc;  --Extra字段里沒有filesort文件排序,充分利用了降序索引
+----+-------------+-------+------------+-------+---------------+-----------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type  | possible_keys | key       | key_len | ref  | rows | filtered | Extra       |
+----+-------------+-------+------------+-------+---------------+-----------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | t1    | NULL       | index | NULL          | idx_c1_c2 | 10      | NULL |    1 |   100.00 | Using index |
+----+-------------+-------+------------+-------+---------------+-----------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)mysql> explain select * from t1 order by c1 desc,c2;  --Extra字段里有Backward index scan,意思是反向掃描索引;
+----+-------------+-------+------------+-------+---------------+-----------+---------+------+------+----------+----------------------------------+
| id | select_type | table | partitions | type  | possible_keys | key       | key_len | ref  | rows | filtered | Extra                            |
+----+-------------+-------+------------+-------+---------------+-----------+---------+------+------+----------+----------------------------------+
|  1 | SIMPLE      | t1    | NULL       | index | NULL          | idx_c1_c2 | 10      | NULL |    1 |   100.00 | Backward index scan; Using index |
+----+-------------+-------+------------+-------+---------------+-----------+---------+------+------+----------+----------------------------------+
1 row in set, 1 warning (0.00 sec)mysql> explain select * from t1 order by c1 desc,c2 desc;  --Extra字段里有filesort文件排序,排序必須按照每個字段定義的排序或按相反順序才能充分利用索引
+----+-------------+-------+------------+-------+---------------+-----------+---------+------+------+----------+-----------------------------+
| id | select_type | table | partitions | type  | possible_keys | key       | key_len | ref  | rows | filtered | Extra                       |
+----+-------------+-------+------------+-------+---------------+-----------+---------+------+------+----------+-----------------------------+
|  1 | SIMPLE      | t1    | NULL       | index | NULL          | idx_c1_c2 | 10      | NULL |    1 |   100.00 | Using index; Using filesort |
+----+-------------+-------+------------+-------+---------------+-----------+---------+------+------+----------+-----------------------------+
1 row in set, 1 warning (0.00 sec)mysql> explain select * from t1 order by c1,c2;    --Extra字段里有filesort文件排序,排序必須按照每個字段定義的排序或按相反順序才能充分利用索引
+----+-------------+-------+------------+-------+---------------+-----------+---------+------+------+----------+-----------------------------+
| id | select_type | table | partitions | type  | possible_keys | key       | key_len | ref  | rows | filtered | Extra                       |
+----+-------------+-------+------------+-------+---------------+-----------+---------+------+------+----------+-----------------------------+
|  1 | SIMPLE      | t1    | NULL       | index | NULL          | idx_c1_c2 | 10      | NULL |    1 |   100.00 | Using index; Using filesort |
+----+-------------+-------+------------+-------+---------------+-----------+---------+------+------+----------+-----------------------------+
1 row in set, 1 warning (0.00 sec)

2、group by 不再隱式排序
mysql 8.0 對于group by 字段不再隱式排序,如需要排序,必須顯式加上order by 子句。

# ====MySQL 5.7演示====
mysql> select count(*),c2 from t1 group by c2;
+----------+------+
| count(*) | c2   |
+----------+------+
|        1 |   10 |
|        2 |   50 |
|        1 |   80 |
|        1 |  100 |
+----------+------+
4 rows in set (0.00 sec)# ====MySQL 8.0演示====
mysql> select count(*),c2 from t1 group by c2;   --8.0版本group by不再默認排序
+----------+------+
| count(*) | c2   |
+----------+------+
|        1 |   10 |
|        2 |   50 |
|        1 |  100 |
|        1 |   80 |
+----------+------+
4 rows in set (0.00 sec)mysql> select count(*),c2 from t1 group by c2 order by c2;  --8.0版本group by不再默認排序,需要自己加order by
+----------+------+
| count(*) | c2   |
+----------+------+
|        1 |   10 |
|        2 |   50 |
|        1 |   80 |
|        1 |  100 |
+----------+------+
4 rows in set (0.00 sec)

3、增加隱藏索引
使用 invisible 關鍵字在創建表或者進行表變更中設置索引為隱藏索引。索引隱藏只是不可見,但是數據庫后臺還是會維護隱藏索引的,在查詢時優化器不使用該索引,即使用force index,優化器也不會使用該索引,同時優化器也不會報索引不存在的錯誤,因為索引仍然真實存在,必要時,也可以把隱藏索引快速恢復成可見。注意,主鍵不能設置為 invisible。
軟刪除就可以使用隱藏索引,比如我們覺得某個索引沒用了,刪除后發現這個索引在某些時候還是有用的,于是又得把這個索引加回來,如果表數據量很大的話,這種操作耗費時間是很多的,成本很高,這時,我們可以將索引先設置為隱藏索引,等到真的確認索引沒用了再刪除。

# 創建t2表,里面的c2字段為隱藏索引
mysql> create table t2(c1 int, c2 int, index idx_c1(c1), index idx_c2(c2) invisible);
Query OK, 0 rows affected (0.02 sec)mysql> show index from t2\G
*************************** 1. row ***************************Table: t2Non_unique: 1Key_name: idx_c1Seq_in_index: 1Column_name: c1Collation: ACardinality: 0Sub_part: NULLPacked: NULLNull: YESIndex_type: BTREEComment: 
Index_comment: Visible: YESExpression: NULL
*************************** 2. row ***************************Table: t2Non_unique: 1Key_name: idx_c2Seq_in_index: 1Column_name: c2Collation: ACardinality: 0Sub_part: NULLPacked: NULLNull: YESIndex_type: BTREEComment: 
Index_comment: Visible: NO   --隱藏索引不可見Expression: NULL
2 rows in set (0.00 sec)mysql> explain select * from t2 where c1=1;
+----+-------------+-------+------------+------+---------------+--------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key    | key_len | ref   | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+--------+---------+-------+------+----------+-------+
|  1 | SIMPLE      | t2    | NULL       | ref  | idx_c1        | idx_c1 | 5       | const |    1 |   100.00 | NULL  |
+----+-------------+-------+------------+------+---------------+--------+---------+-------+------+----------+-------+
1 row in set, 1 warning (0.00 sec)mysql> explain select * from t2 where c2=1;  --隱藏索引c2不會被使用
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra       |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | t2    | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    1 |   100.00 | Using where |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)mysql> select @@optimizer_switch\G   --查看各種參數
*************************** 1. row ***************************
@@optimizer_switch: index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,engine_condition_pushdown=on,index_condition_pushdown=on,mrr=on,mrr_cost_based=on,block_nested_loop=on,batched_key_access=off,materialization=on,semijoin=on,loosescan=on,firstmatch=on,duplicateweedout=on,subquery_materialization_cost_based=on,use_index_extensions=on,condition_fanout_filter=on,derived_merge=on,use_invisible_indexes=off,skip_scan=on,hash_join=on
1 row in set (0.00 sec)mysql> set session optimizer_switch="use_invisible_indexes=on";  ----在會話級別設置查詢優化器可以看到隱藏索引
Query OK, 0 rows affected (0.00 sec)mysql> select @@optimizer_switch\G
*************************** 1. row ***************************
@@optimizer_switch: index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,engine_condition_pushdown=on,index_condition_pushdown=on,mrr=on,mrr_cost_based=on,block_nested_loop=on,batched_key_access=off,materialization=on,semijoin=on,loosescan=on,firstmatch=on,duplicateweedout=on,subquery_materialization_cost_based=on,use_index_extensions=on,condition_fanout_filter=on,derived_merge=on,use_invisible_indexes=on,skip_scan=on,hash_join=on
1 row in set (0.00 sec)mysql> explain select * from t2 where c2=1;
+----+-------------+-------+------------+------+---------------+--------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key    | key_len | ref   | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+--------+---------+-------+------+----------+-------+
|  1 | SIMPLE      | t2    | NULL       | ref  | idx_c2        | idx_c2 | 5       | const |    1 |   100.00 | NULL  |
+----+-------------+-------+------------+------+---------------+--------+---------+-------+------+----------+-------+
1 row in set, 1 warning (0.00 sec)mysql> alter table t2 alter index idx_c2 visible;
Query OK, 0 rows affected (0.02 sec)
Records: 0  Duplicates: 0  Warnings: 0mysql> alter table t2 alter index idx_c2 invisible;
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0

4、新增函數索引
之前我們知道,如果在查詢中加入了函數,索引不生效,所以MySQL 8引入了函數索引,MySQL 8.0.13開始支持在索引中使用函數(表達式)的值。
函數索引基于虛擬列功能實現,在MySQL中相當于新增了一個列,這個列會根據你的函數來進行計算結果,然后使用函數索引的時候就會用這個計算后的列作為索引。

mysql> create table t3(c1 varchar(10),c2 varchar(10));
Query OK, 0 rows affected (0.02 sec)mysql> create index idx_c1 on t3(c1);     --創建普通索引
Query OK, 0 rows affected (0.03 sec)
Records: 0  Duplicates: 0  Warnings: 0mysql> create index func_idx on t3((UPPER(c2)));  --創建一個大寫的函數索引
Query OK, 0 rows affected (0.03 sec)
Records: 0  Duplicates: 0  Warnings: 0mysql> show index from t3\G
*************************** 1. row ***************************Table: t3Non_unique: 1Key_name: idx_c1Seq_in_index: 1Column_name: c1Collation: ACardinality: 0Sub_part: NULLPacked: NULLNull: YESIndex_type: BTREEComment: 
Index_comment: Visible: YESExpression: NULL
*************************** 2. row ***************************Table: t3Non_unique: 1Key_name: func_idxSeq_in_index: 1Column_name: NULLCollation: ACardinality: 0Sub_part: NULLPacked: NULLNull: YESIndex_type: BTREEComment: 
Index_comment: Visible: YESExpression: upper(`c2`)    --函數表達式
2 rows in set (0.00 sec)mysql> explain select * from t3 where upper(c1)='ZHUGE';
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra       |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | t3    | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    1 |   100.00 | Using where |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)mysql> explain select * from t3 where upper(c2)='ZHUGE';  --使用了函數索引
+----+-------------+-------+------------+------+---------------+----------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key      | key_len | ref   | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+----------+---------+-------+------+----------+-------+
|  1 | SIMPLE      | t3    | NULL       | ref  | func_idx      | func_idx | 43      | const |    1 |   100.00 | NULL  |
+----+-------------+-------+------------+------+---------------+----------+---------+-------+------+----------+-------+
1 row in set, 1 warning (0.00 sec)

5、innodb存儲引擎select for update跳過鎖等待
對于select … for share(8.0新增加查詢共享鎖的語法)或 select … for update, 在語句后面添加NOWAIT、SKIP LOCKED語法可以跳過鎖等待,或者跳過鎖定。
在5.7及之前的版本,select…for update,如果獲取不到鎖,會一直等待,直到innodb_lock_wait_timeout超時。
在8.0版本,通過添加nowait,skip locked語法,能夠立即返回。如果查詢的行已經加鎖,那么nowait會立即報錯返回,而skip locked也會立即返回,只是返回的結果中不包含被鎖定的行。
應用場景比如查詢余票記錄,如果某些記錄已經被鎖定,用skip locked可以跳過被鎖定的記錄,只返回沒有鎖定的記錄,提高系統性能。

# 先打開一個session1:
mysql> select * from t1;
+------+------+
| c1   | c2   |
+------+------+
|    1 |   10 |
|    2 |   50 |
|    3 |   50 |
|    4 |  100 |
|    5 |   80 |
+------+------+
5 rows in set (0.00 sec)mysql> begin;
Query OK, 0 rows affected (0.00 sec)mysql> update t1 set c2 = 60 where c1 = 2;     --鎖定第二條記錄
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0# 另外一個session2:    
mysql> select * from t1 where c1 = 2 for update;   --等待超時
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transactionmysql> select * from t1 where c1 = 2 for update nowait;   --查詢立即返回
ERROR 3572 (HY000): Statement aborted because lock(s) could not be acquired immediately and NOWAIT is set.mysql> select * from t1 for update skip locked;  --查詢立即返回,過濾掉了第二行記錄
+------+------+
| c1   | c2   |
+------+------+
|    1 |   10 |
|    3 |   50 |
|    4 |  100 |
|    5 |   80 |
+------+------+
4 rows in set (0.00 sec)

6、新增innodb_dedicated_server自適應參數
能夠讓InnoDB根據服務器上檢測到的內存大小自動配置innodb_buffer_pool_size,innodb_log_file_size等參數,會盡可能多的占用系統可占用資源提升性能。解決非專業人員安裝數據庫后默認初始化數據庫參數默認值偏低的問題,前提是服務器是專用來給MySQL數據庫的,如果還有其他軟件或者資源或者多實例MySQL使用,不建議開啟該參數,不然會影響其它程序。

mysql> show variables like '%innodb_dedicated_server%';   --默認是OFF關閉,修改為ON打開
+-------------------------+-------+
| Variable_name           | Value |
+-------------------------+-------+
| innodb_dedicated_server | OFF   |
+-------------------------+-------+
1 row in set (0.02 sec)

7、死鎖檢查控制
MySQL 8.0 (MySQL 5.7.15)增加了一個新的動態變量 innodb_deadlock_detect,用于控制系統是否執行 InnoDB 死鎖檢查,默認是打開的。死鎖檢測會耗費數據庫性能的,對于高并發的系統,我們可以關閉死鎖檢測功能,提高系統性能。但是我們要確保系統極少情況會發生死鎖,同時要將鎖等待超時參數調小一點,以防出現死鎖等待過久的情況。

mysql> show variables like '%innodb_deadlock_detect%';  --默認是打開的
+------------------------+-------+
| Variable_name          | Value |
+------------------------+-------+
| innodb_deadlock_detect | ON    |
+------------------------+-------+
1 row in set, 1 warning (0.01 sec)

8、undo文件不再使用系統表空間
默認創建2個UNDO表空間,不再使用系統表空間。
在這里插入圖片描述
在這里插入圖片描述

9、 binlog日志過期時間精確到秒
之前是天,并且參數名稱發生變化. 在8.0版本之前,binlog日志過期時間設置都是設置expire_logs_days參數,而在8.0版本中,MySQL默認使用binlog_expire_logs_seconds參數。
在這里插入圖片描述

10、窗口函數(Window Functions):也稱分析函數
從 MySQL 8.0 開始,新增了一個叫窗口函數的概念,它可以用來實現若干新的查詢方式。窗口函數與 SUM()、COUNT() 這種分組聚合函數類似,在聚合函數后面加上over()就變成窗口函數了,在括號里可以加上partition by等分組關鍵字指定如何分組,窗口函數即便分組也不會將多行查詢結果合并為一行,而是將結果放回多行當中,即窗口函數不需要再使用 GROUP BY。

# 創建一張賬戶余額表
CREATE TABLE `account_channel` (`id` int NOT NULL AUTO_INCREMENT,`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '姓名',`channel` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '賬戶渠道',`balance` int DEFAULT NULL COMMENT '余額',PRIMARY KEY (`id`)
) ENGINE=InnoDB;# 插入一些示例數據
INSERT INTO `account_channel` (`id`, `name`, `channel`, `balance`) VALUES ('1', 'zhuge', 'wx', '100');
INSERT INTO `account_channel` (`id`, `name`, `channel`, `balance`) VALUES ('2', 'zhuge', 'alipay', '200');
INSERT INTO `account_channel` (`id`, `name`, `channel`, `balance`) VALUES ('3', 'zhuge', 'yinhang', '300');
INSERT INTO `account_channel` (`id`, `name`, `channel`, `balance`) VALUES ('4', 'lilei', 'wx', '200');
INSERT INTO `account_channel` (`id`, `name`, `channel`, `balance`) VALUES ('5', 'lilei', 'alipay', '100');
INSERT INTO `account_channel` (`id`, `name`, `channel`, `balance`) VALUES ('6', 'hanmeimei', 'wx', '500');mysql> select * from account_channel;
+----+-----------+---------+---------+
| id | name      | channel | balance |
+----+-----------+---------+---------+
|  1 | zhuge     | wx      |     100 |
|  2 | zhuge     | alipay  |     200 |
|  3 | zhuge     | yinhang |     300 |
|  4 | lilei     | wx      |     200 |
|  5 | lilei     | alipay  |     100 |
|  6 | hanmeimei | wx      |     500 |
+----+-----------+---------+---------+
6 rows in set (0.00 sec)mysql> select name,sum(balance) from account_channel group by name;
+-----------+--------------+
| name      | sum(balance) |
+-----------+--------------+
| zhuge     |          600 |
| lilei     |          300 |
| hanmeimei |          500 |
+-----------+--------------+
3 rows in set (0.00 sec)# 在聚合函數后面加上over()就變成分析函數了,后面可以不用再加group by制定分組,因為在over里已經用partition關鍵字指明了如何分組計算,這種可以保留原有表數據的結構,不會像分組聚合函數那樣每組只返回一條數據
mysql> select name,channel,balance,sum(balance) over(partition by name) as sum_balance from account_channel;
+-----------+---------+---------+-------------+
| name      | channel | balance | sum_balance |
+-----------+---------+---------+-------------+
| hanmeimei | wx      |     500 |         500 |
| lilei     | wx      |     200 |         300 |
| lilei     | alipay  |     100 |         300 |
| zhuge     | wx      |     100 |         600 |
| zhuge     | alipay  |     200 |         600 |
| zhuge     | yinhang |     300 |         600 |
+-----------+---------+---------+-------------+
6 rows in set (0.00 sec)mysql> select name,channel,balance,sum(balance) over(partition by name order by balance) as sum_balance from account_channel;
+-----------+---------+---------+-------------+
| name      | channel | balance | sum_balance |
+-----------+---------+---------+-------------+
| hanmeimei | wx      |     500 |         500 |
| lilei     | alipay  |     100 |         100 |
| lilei     | wx      |     200 |         300 |
| zhuge     | wx      |     100 |         100 |
| zhuge     | alipay  |     200 |         300 |
| zhuge     | yinhang |     300 |         600 |
+-----------+---------+---------+-------------+
6 rows in set (0.00 sec)# over()里如果不加條件,則默認使用整個表的數據做運算
mysql> select name,channel,balance,sum(balance) over() as sum_balance from account_channel;
+-----------+---------+---------+-------------+
| name      | channel | balance | sum_balance |
+-----------+---------+---------+-------------+
| zhuge     | wx      |     100 |        1400 |
| zhuge     | alipay  |     200 |        1400 |
| zhuge     | yinhang |     300 |        1400 |
| lilei     | wx      |     200 |        1400 |
| lilei     | alipay  |     100 |        1400 |
| hanmeimei | wx      |     500 |        1400 |
+-----------+---------+---------+-------------+
6 rows in set (0.00 sec)mysql> select name,channel,balance,avg(balance) over(partition by name) as avg_balance from account_channel;
+-----------+---------+---------+-------------+
| name      | channel | balance | avg_balance |
+-----------+---------+---------+-------------+
| hanmeimei | wx      |     500 |    500.0000 |
| lilei     | wx      |     200 |    150.0000 |
| lilei     | alipay  |     100 |    150.0000 |
| zhuge     | wx      |     100 |    200.0000 |
| zhuge     | alipay  |     200 |    200.0000 |
| zhuge     | yinhang |     300 |    200.0000 |
+-----------+---------+---------+-------------+
6 rows in set (0.00 sec)專用窗口函數:
- 序號函數:ROW_NUMBER()RANK()DENSE_RANK()
- 分布函數:PERCENT_RANK()CUME_DIST()
- 前后函數:LAG()LEAD()
- 頭尾函數:FIRST_VALUE()LAST_VALUE()
- 其它函數:NTH_VALUE()NTILE()
# 按照balance字段排序,展示序號
mysql> select name,channel,balance,row_number() over(order by balance) as row_number1 from account_channel;
+-----------+---------+---------+-------------+
| name      | channel | balance | row_number1 |
+-----------+---------+---------+-------------+
| zhuge     | wx      |     100 |           1 |
| lilei     | alipay  |     100 |           2 |
| zhuge     | alipay  |     200 |           3 |
| lilei     | wx      |     200 |           4 |
| zhuge     | yinhang |     300 |           5 |
| hanmeimei | wx      |     500 |           6 |
+-----------+---------+---------+-------------+
6 rows in set (0.00 sec)# 按照balance字段排序,first_value()選出排第一的余額
mysql> select name,channel,balance,first_value(balance) over(order by balance) as first1 from account_channel;
+-----------+---------+---------+--------+
| name      | channel | balance | first1 |
+-----------+---------+---------+--------+
| zhuge     | wx      |     100 |    100 |
| lilei     | alipay  |     100 |    100 |
| zhuge     | alipay  |     200 |    100 |
| lilei     | wx      |     200 |    100 |
| zhuge     | yinhang |     300 |    100 |
| hanmeimei | wx      |     500 |    100 |
+-----------+---------+---------+--------+
6 rows in set (0.01 sec)

11、默認字符集由latin1變為utf8mb4
在8.0版本之前,默認字符集為latin1,utf8指向的是utf8mb3,8.0版本默認字符集為utf8mb4,utf8默認指向的也是utf8mb4。

12、MyISAM系統表全部換成InnoDB表
將系統表(mysql)和數據字典表全部改為InnoDB存儲引擎,默認的MySQL實例將不包含MyISAM表,除非手動創建MyISAM表。

13、元數據存儲變動
MySQL 8.0刪除了之前版本的元數據文件,例如表結構.frm等文件,全部集中放入mysql.ibd文件里。可以看見下圖test庫文件夾里已經沒有了frm文件。

在這里插入圖片描述
在這里插入圖片描述

14、自增變量持久化
在8.0之前的版本,自增主鍵AUTO_INCREMENT的值如果大于max(primary key)+1,在MySQL重啟后,會重置AUTO_INCREMENT=max(primary key)+1,這種現象在某些情況下會導致業務主鍵沖突或者其他難以發現的問題。自增主鍵重啟重置的問題很早就被發現(https://bugs.mysql.com/bug.php?id=199),一直到8.0才被解決,8.0版本將會對AUTO_INCREMENT值進行持久化,MySQL重啟后,該值將不會改變。

# ====MySQL 5.7演示====
mysql> create table t(id int auto_increment primary key,c1 varchar(20));
Query OK, 0 rows affected (0.03 sec)mysql> insert into t(c1) values('zhuge1'),('zhuge2'),('zhuge3');
Query OK, 3 rows affected (0.00 sec)
Records: 3  Duplicates: 0  Warnings: 0mysql> select * from t;
+----+--------+
| id | c1     |
+----+--------+
|  1 | zhuge1 |
|  2 | zhuge2 |
|  3 | zhuge3 |
+----+--------+
3 rows in set (0.00 sec)mysql> delete from t where id = 3;
Query OK, 1 row affected (0.01 sec)mysql> select * from t;
+----+--------+
| id | c1     |
+----+--------+
|  1 | zhuge1 |
|  2 | zhuge2 |
+----+--------+
2 rows in set (0.00 sec)mysql> exit;
Bye# 重啟MySQL服務,并重新連接MySQL
mysql> insert into t(c1) values('zhuge4');
Query OK, 1 row affected (0.01 sec)mysql> select * from t;
+----+--------+
| id | c1     |
+----+--------+
|  1 | zhuge1 |
|  2 | zhuge2 |
|  3 | zhuge4 |
+----+--------+
3 rows in set (0.00 sec)mysql> update t set id = 5 where c1 = 'zhuge1';
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0mysql> select * from t;
+----+--------+
| id | c1     |
+----+--------+
|  2 | zhuge2 |
|  3 | zhuge4 |
|  5 | zhuge1 |
+----+--------+
3 rows in set (0.00 sec)mysql> insert into t(c1) values('zhuge5');
Query OK, 1 row affected (0.01 sec)mysql> select * from t;
+----+--------+
| id | c1     |
+----+--------+
|  2 | zhuge2 |
|  3 | zhuge4 |
|  4 | zhuge5 |
|  5 | zhuge1 |
+----+--------+
4 rows in set (0.00 sec)mysql> insert into t(c1) values('zhuge6');
ERROR 1062 (23000): Duplicate entry '5' for key 'PRIMARY'# ====MySQL 8.0演示====
mysql> create table t(id int auto_increment primary key,c1 varchar(20));
Query OK, 0 rows affected (0.02 sec)mysql> insert into t(c1) values('zhuge1'),('zhuge2'),('zhuge3');
Query OK, 3 rows affected (0.00 sec)
Records: 3  Duplicates: 0  Warnings: 0mysql> select * from t;
+----+--------+
| id | c1     |
+----+--------+
|  1 | zhuge1 |
|  2 | zhuge2 |
|  3 | zhuge3 |
+----+--------+
3 rows in set (0.00 sec)mysql> delete from t where id = 3;
Query OK, 1 row affected (0.01 sec)mysql> select * from t;
+----+--------+
| id | c1     |
+----+--------+
|  1 | zhuge1 |
|  2 | zhuge2 |
+----+--------+
2 rows in set (0.00 sec)mysql> exit;
Bye
[root@localhost ~]# service mysqld restart
Shutting down MySQL.... SUCCESS! 
Starting MySQL... SUCCESS! # 重新連接MySQL
mysql> insert into t(c1) values('zhuge4');
Query OK, 1 row affected (0.00 sec)mysql> select * from t;  --生成的id為4,不是3
+----+--------+
| id | c1     |
+----+--------+
|  1 | zhuge1 |
|  2 | zhuge2 |
|  4 | zhuge4 |
+----+--------+
3 rows in set (0.00 sec)mysql> update t set id = 5 where c1 = 'zhuge1';
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0mysql> select * from t;
+----+--------+
| id | c1     |
+----+--------+
|  2 | zhuge2 |
|  4 | zhuge4 |
|  5 | zhuge1 |
+----+--------+
3 rows in set (0.00 sec)mysql> insert into t(c1) values('zhuge5');
Query OK, 1 row affected (0.00 sec)mysql> select * from t;
+----+--------+
| id | c1     |
+----+--------+
|  2 | zhuge2 |
|  4 | zhuge4 |
|  5 | zhuge1 |
|  6 | zhuge5 |
+----+--------+
4 rows in set (0.00 sec)

15、DDL原子化
InnoDB表的DDL支持事務完整性,要么成功要么回滾。
MySQL 8.0 開始支持原子 DDL 操作,其中與表相關的原子 DDL 只支持 InnoDB 存儲引擎。一個原子 DDL 操作內容包括:更新數據字典,存儲引擎層的操作,在 binlog 中記錄 DDL 操作。支持與表相關的 DDL:數據庫、表空間、表、索引的 CREATE、ALTER、DROP 以及 TRUNCATE TABLE。支持的其它 DDL :存儲程序、觸發器、視圖、UDF 的 CREATE、DROP 以及ALTER 語句。支持賬戶管理相關的 DDL:用戶和角色的 CREATE、ALTER、DROP 以及適用的 RENAME等等。

# MySQL 5.7
mysql> show tables;
+----------------+
| Tables_in_test |
+----------------+
| account        |
| actor          |
| employee       |
| film           |
| film_actor     |
| leaf_id        |
| t1             |
| test_innodb    |
| test_myisam    |
| test_order_id  |
+----------------+
10 rows in set (0.01 sec)mysql> drop table t1,t2;  //刪除表報錯不會回滾,t1表會被刪除
ERROR 1051 (42S02): Unknown table 'test.t2'
mysql> show tables;
+----------------+
| Tables_in_test |
+----------------+
| account        |
| actor          |
| employee       |
| film           |
| film_actor     |
| leaf_id        |
| test_innodb    |
| test_myisam    |
| test_order_id  |
+----------------+
9 rows in set (0.00 sec)# MySQL 8.0  
mysql> show tables;
+----------------+
| Tables_in_test |
+----------------+
| account        |
| actor          |
| employee       |
| film           |
| film_actor     |
| leaf_id        |
| t1             |
| test_innodb    |
| test_myisam    |
| test_order_id  |
+----------------+
10 rows in set (0.00 sec)mysql> drop table t1,t2;  //刪除表報錯會回滾,t1表依然還在
ERROR 1051 (42S02): Unknown table 'test.t2'
mysql> show tables;  
+----------------+
| Tables_in_test |
+----------------+
| account        |
| actor          |
| employee       |
| film           |
| film_actor     |
| leaf_id        |
| t1             |
| test_innodb    |
| test_myisam    |
| test_order_id  |
+----------------+
10 rows in set (0.00 sec)

16、參數修改持久化
MySQL 8.0版本支持在線修改全局參數并持久化,通過加上PERSIST關鍵字,可以將修改的參數持久化到新的配置文件(mysqld-auto.cnf)中,重啟MySQL時,可以從該配置文件獲取到最新的配置參數。set global 設置的變量參數在mysql重啟后會失效。

mysql> set persist innodb_lock_wait_timeout=25;
系統會在數據目錄下生成一個包含json格式的mysqld-auto.cnf 的文件,格式化后如下所示,當my.cnf 和mysqld-auto.cnf 同時存在時,后者具有更高優先級。
{"Version": 1,"mysql_server": {"innodb_lock_wait_timeout": {"Value": "25","Metadata": {"Timestamp": 1675290252103863,"User": "root","Host": "localhost"}}}
}

在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/96138.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/96138.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/96138.shtml

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

相關文章

leetcode hot100 二叉搜索樹

二叉搜索樹的第k小的數class Solution:def kthSmallest(self, root: Optional[TreeNode], k: int) -> int:# 二叉搜索樹的中序遍歷是 升序排列的, 求第k小的,即第k個數self.res []def fun(root):if not root:returnfun(root.left)if root:self.res.a…

從Sonnet到Opus:一次解決RAG知識庫流式輸出難題的探索

又到周末,還得消耗消耗 ?? anyrouter 上的Claude資源,萬一哪天都不能用了,也是浪費。 2025/9/5,Claude AI 的母公司 Anthropic 發布了一項新政策:即日起,Anthropic將不再對中國控股公司及其海外子公司開放…

「數據獲取」中國科技統計年鑒(1991-2024)Excel

02、數據詳情數據名稱:《中國科技統計年鑒》(1991-2024年)數據年份:1991-202403、數據截圖 04、獲取方式(獲取方式看綁定的資源)

SimLingo:純視覺框架下的自動駕駛視覺 - 語言 - 動作融合模型

摘要 本文深入探討了 SimLingo,一個在自動駕駛領域具有開創性意義的視覺-語言-動作一體化模型。SimLingo 創新性地將自動駕駛、語言理解和指令感知控制整合到一個統一的純攝像頭框架中,顯著提升了自動駕駛系統在復雜環境中的感知、決策與執行能力。該模…

第五十四天(SQL注入數據類型參數格式JSONXML編碼加密符號閉合復盤報告)

#SQL注入產生原理: 代碼中執行的SQL語句存在可控變量導致 #常見SQL注入的利用過程: 1、判斷數據庫類型 2、判斷參數類型及格式 3、判斷數據格式及提交 4、判斷數據回顯及防護 5、獲取數據庫名,表名,列名 5、獲取對應數據及…

VMWare上搭建Hive集群

文章目錄1. MySQL安裝2. 安裝Hive集群3. 使用Hive客戶端4. 實戰總結本實戰在VMware上搭建Hive集群,集成MySQL作為元數據存儲,完成Hive環境配置、元數據初始化及HDFS倉庫目錄創建,實現Hive on Hadoop的SQL查詢能力,為大數據分析提供…

Android網絡之WIFI技術網絡模型概述

文章目錄術語1、WLAN與WIFI2、802.11 WIFI無線網絡標準演進3、WIFI5、WIFI6和WIFI7的最高速率對比4、WIFI網絡中的各個角色(元件)1)網絡拓撲架構圖5、802.11權威指南1)OSI與TCP/IP2)IEEE 802.11協議簇介紹3&#xff09…

游戲中的設計模式——第三篇 簡單工廠模式

5. 簡單工廠模式 5.1 簡單工廠模式的定義 簡單工廠模式的核心是定義一個創建對象的接口,將對象的創建和本身的業務邏輯分離,降低系統的耦合度,使得兩個修改起來相對容易些,當以后實現改變時,只需要修改工廠類即可。 5.…

基于SVN搭建企業內部知識庫系統實踐

一、準備工作 CentOS 7 服務器:確保你有 root 或 sudo 權限,可以訪問該服務器。Windows 客戶端:你將需要在 Windows 上安裝 TortoiseSVN 客戶端來與 SVN 服務器交互。防火墻:確保你的防火墻已開放 3690 端口,用于 SVN…

SQL注入7----(盲注與回顯)

一.前言 在我們的注入語句被帶入數據庫查詢但卻什么都沒有返回的情況我們該怎么辦?例如應用程序就會返回 一個"通用的"的頁面,或者重定向一個通用頁面(可能為網站首頁)。這時,我們之前學習的SQL注入辦 法就…

尚硅谷宋紅康JVM全套教程(詳解java虛擬機)

https://www.bilibili.com/opus/1071553679925968898 案例7:日均百萬訂單系統JVM參數設置 https://github.com/wei198621/jvm_by_atguigu https://github.com/xftxyz2001/atguigu-jvm/blob/main/JavaYouthdocsJVM/%E7%AC%AC1%E7%AB%A0-JVM%E4%B8%8EJava%E4%BD%…

鴻蒙NEXT開發實戰:圖片顯示、幾何圖形與自定義繪制詳解

探索HarmonyOS NEXT強大的圖形渲染能力,從圖片展示到自定義繪圖 HarmonyOS NEXT作為華為自主研發的操作系統,為開發者提供了一套豐富而強大的圖形渲染能力。無論是顯示圖片、繪制幾何圖形,還是實現復雜的自定義繪圖,鴻蒙都提供了簡…

python + Flask模塊學習 2 接收用戶請求并返回json數據

用到的模塊還是flask,用到的類有Flask, request, jsonfiy 🙂 目錄 1、GET請求 2、POST請求 1、表單格式 2、json格式 就醬,也比較簡單,下一篇說簡單的授權,簡單來說就是比如用戶付費買了服…

國內外常用的免費BUG管理工具選型

幫助用戶根據自身情況做決定,比如團隊規模、技術能力、是否需要移動端支持等。避免只是羅列工具,而是提供實際選擇的維度。 國內外常用的免費BUG管理工具選擇非常豐富,從輕量級到功能全面型都有覆蓋。我將它們分為幾類,并詳細介紹…

JavaScript的事件循環機制

1.事件循環的理解JavaScript是單線程的,意味著它一次只能執行一個任務。而事件循環就是去協調在JavaScript環境中運行的同步任務、異步任務(微任務、宏任務)的執行順序的一種機制。它是 JavaScript 實現單線程非阻塞異步執行的核心。2.事件循環的執行順序同步任務—…

數據結構——棧(Java)

目錄 一定義. 入棧 出棧 二.棧與線性表的關系 三.棧的實現方式 四.鏈表實現棧 1.結點的API設計 2.棧的API設計 2.1棧的初始化設計 2.2元素入棧 2.3元素出棧 五.括號匹配問題 完整代碼展示 答案 一定義. 棧是一種基于先進后出(FILO)的數據…

科研筆記:數學建模啟發的課題研究方法

借鑒數學建模的思路解決科學問題或開展課題研究,核心是將實際問題抽象為數學框架,通過定量分析、邏輯推演和驗證優化,實現對問題的精準描述、解釋或預測。其本質是“從現實到數學,再從數學回歸現實”的迭代過程,適用于…

Agent落地到底選擇LangChain 還是 LangGraph

核心概念 LangChain:一個用于構建由大型語言模型驅動的應用程序的框架。它提供了大量的組件和現成的鏈,旨在簡化和標準化應用程序與LLM交互的過程。 LangGraph:一個用于在LangChain之上構建有狀態、多參與者的 工作流 的庫。它特別擅長處理具有循環、分支和復雜協調的代理(…

ChatGPT下的相關聊天提示詞

問:如果我覺得一個子對話里,聊天聊得太多,在這個項目下新開一個子對話,但是不想把上次太多的信息 都復制過來,有沒有什么辦法關鍵詞:項目、子對話,上下文ChatGPT:有辦法的 ?在 ChatGPT 里&…

最新PDF版本!Acrobat Pro DC 2025,解壓即用版

軟件介紹 Adobe Acrobat Pro DC 2025 是全球知名的 PDF 編輯神器,被稱為 “最牛 PDF 工具”,能輕松解決 PDF 編輯、創建、轉換等難題,本次分享的版本解壓即可使用。 軟件特點 然解壓即可使用不用登錄注冊最新版本 軟件使用 我們打開軟件選…