學習 MySQL 需要知道的 28 個小技巧
在公眾號后臺回復:JGNB,可獲取杰哥原創(chuàng)的 PDF 手冊。
前言
必備加薪神器,那么,一直說學習數(shù)據(jù)庫、學 MySQL,到底是要學習它的哪些東西呢?一、如何快速掌握 MySQL?
MySQL5.7 還是 MySQL8.0 都不例外!二、技巧分享
1、MySQL 中如何使用特殊字符?
',雙引號 ",反斜線 \ 等符號,這些符號在 MySQL 中不能直接輸入使用,否則會產(chǎn)生意料之外的結果。lucifer's dog,其中的單引號 ' 號,如果不做轉義,則無法成功執(zhí)行:mysql> create table lucifer (id int,name char(100));
Query OK, 0 rows affected (0.02 sec)
mysql> insert into lucifer values (1,'lucifer's dog');
'>
'> mysql>
^C
mysql>
\ 開頭,所以在使用單引號和雙引號時應分別輸入 \' 或者 \",輸入反斜線時應該輸入 \\,其他特殊字符還有回車符 \r,換行符 \n,制表符 \tab,退格符 \b 等。mysql> create table lucifer (id int,name char(100));
Query OK, 0 rows affected (0.03 sec)
mysql> insert into lucifer values (1,'lucifer\'s dog');
Query OK, 1 row affected (0.00 sec)
mysql> select * from lucifer;
+------+---------------+
| id | name |
+------+---------------+
| 1 | lucifer's dog |
+------+---------------+
1 row in set (0.00 sec)
mysql>
2、MySQL 中可以存儲文件嗎?
BLOB 和 TEXT 字段類型可以存儲數(shù)據(jù)量較大的文件,可以使用這些數(shù)據(jù)類型 存儲圖像、聲音或者是大容量的文本內(nèi)容,例如網(wǎng)頁或者文檔。mysql> create table view(id int unsigned NOT NULL AUTO_INCREMENT, catid int,title varchar(256),picture MEDIUMBLOB, content TEXT,PRIMARY KEY (id));
Query OK, 0 rows affected (0.03 sec)
mysql> show fields from view;
+---------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------+--------------+------+-----+---------+----------------+
| id | int unsigned | NO | PRI | NULL | auto_increment |
| catid | int | YES | | NULL | |
| title | varchar(256) | YES | | NULL | |
| picture | mediumblob | YES | | NULL | |
| content | text | YES | | NULL | |
+---------+--------------+------+-----+---------+----------------+
5 rows in set (0.00 sec)
mysql>
3、MySQL 中如何執(zhí)行區(qū)分大小寫的字符串比較?
不區(qū)分大小寫 的,因此字符串比較函數(shù)也不區(qū)分大小寫。mysql> select 'TRUE' from dual where 'DOG' = 'dog';
+------+
| TRUE |
+------+
| TRUE |
+------+
1 row in set (0.00 sec)
mysql> select 'TRUE' from dual where BINARY'DOG' = 'dog';
Empty set (0.00 sec)
mysql>
4、如何從日期時間值中獲取年、月、日等部分日期或時間值?
mysql> create table lucifer(date date);
Query OK, 0 rows affected (0.04 sec)
mysql> show fields from lucifer;
+-------+------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+------+------+-----+---------+-------+
| date | date | YES | | NULL | |
+-------+------+------+-----+---------+-------+
1 row in set (0.00 sec)
mysql> insert into lucifer values (now());
Query OK, 1 row affected, 1 warning (0.00 sec)
mysql> select * from lucifer;
+------------+
| date |
+------------+
| 2021-11-25 |
+------------+
1 row in set (0.00 sec)
2021-11-25,如果只需要獲得年值,可以輸入 LEFT(date, 4),這樣就獲得了字符串左邊開始長度為 4 的子字符串,即 YEAR 部分的值;mysql> select LEFT(date, 4) from lucifer;
+---------------+
| LEFT(date, 4) |
+---------------+
| 2021 |
+---------------+
1 row in set (0.00 sec)
MID(date,6,2),字符串第 6 個字符開始,長度為 2 的子字符串正好為 date 中的月份值。同理,讀者可以根據(jù)其他日期和時間的位置,計算并獲取相應的值。mysql> select MID(date,6,2) from lucifer;
+---------------+
| MID(date,6,2) |
+---------------+
| 11 |
+---------------+
1 row in set (0.00 sec)
5、如何改變默認的字符集?
CONVERT() 函數(shù)改變指定字符串的默認字符集!修改配置文件。SHOW VARIABLES LIKE 'character_set_%'; 或者 status 命令查看當前字符集,以進行對比。mysql> SHOW VARIABLES LIKE 'character_set_%';
+--------------------------+----------------------------+
| Variable_name | Value |
+--------------------------+----------------------------+
| character_set_client | latin1 |
| character_set_connection | latin1 |
| character_set_database | utf8mb3 |
| character_set_filesystem | binary |
| character_set_results | latin1 |
| character_set_server | utf8mb4 |
| character_set_system | utf8mb3 |
| character_sets_dir | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+
8 rows in set (0.00 sec)
mysql> status
--------------
mysql Ver 8.0.26-0ubuntu0.21.04.3 for Linux on aarch64 ((Ubuntu))
Connection id: 10
Current database:
Current user: root@localhost
SSL: Not in use
Current pager: stdout
Using outfile: ''
Using delimiter: ;
Server version: 8.0.26-0ubuntu0.21.04.3 (Ubuntu)
Protocol version: 10
Connection: Localhost via UNIX socket
Server characterset: utf8mb4
Db characterset: utf8mb4
Client characterset: latin1
Conn. characterset: latin1
UNIX socket: /var/run/mysqld/mysqld.sock
Binary data as: Hexadecimal
Uptime: 36 min 55 sec
Threads: 2 Questions: 325 Slow queries: 0 Opens: 181 Flush tables: 3 Open tables: 69 Queries per second avg: 0.146
--------------
mysql>
my.cnf,該文件在 MySQL 的安裝目錄下面。修改配置文件中的 default-character-set 和 character-set-server 參數(shù)值,將其改為想要的字符集名稱,如 gbk、gb2312、latinl 等,修改完之后重新啟動 MySQL 服務,即可生效。## 找到 my.cnf 位置
root@modb:~# find /etc -iname my.cnf -print
/etc/alternatives/my.cnf
/etc/mysql/my.cnf
## 修改字符集
在[client ]下面加入
default-character-set=utf8
在[ mysqld ] 下面加
character_set_server=utf8
## 重啟 mysql 生效
service mysql restart
SHOW VARIABLES LIKE 'character_set_%'; 或者 status 命令查看修改結果!6、DISTINCT 可以應用于所有的列嗎?
DESC,這個關鍵字只能對其前面的列 進行降序排列。mysql> select * from lucifer;
+------+----------+
| id | name |
+------+----------+
| 1 | lucifer |
| 2 | lucifer1 |
| 3 | lucifer2 |
+------+----------+
3 rows in set (0.00 sec)
mysql> select * from lucifer order by id desc;
+------+----------+
| id | name |
+------+----------+
| 3 | lucifer2 |
| 2 | lucifer1 |
| 1 | lucifer |
+------+----------+
3 rows in set (0.00 sec)
DESC 關鍵字。mysql> select * from lucifer order by id desc,name desc;
+------+----------+
| id | name |
+------+----------+
| 3 | lucifer2 |
| 2 | lucifer1 |
| 1 | lucifer |
+------+----------+
3 rows in set (0.00 sec)
DISTINCT 不同,DISTINCT 不能部分使用。換句話說,DISTINCT 關鍵字應用于所有列而不僅是它后面的第一個指定列。mysql> select * from lucifer;
+------+-----------+--------+------+
| id | name | sex | age |
+------+-----------+--------+------+
| 1 | xiaoli | male | 20 |
| 1 | xiaoliu | female | 21 |
| 1 | xiaozhang | female | 21 |
| 1 | xiaowu | female | 21 |
+------+-----------+--------+------+
4 rows in set (0.00 sec)
mysql> select distinct sex,age from lucifer;
+--------+------+
| sex | age |
+--------+------+
| male | 20 |
| female | 21 |
+--------+------+
2 rows in set (0.00 sec)
mysql>
7、ORDER BY 可以和 LIMIT 混合使用嗎?
LIMIT,則必須位于 ORDER BY 之后,如果子句順序不正確,MySQL 將產(chǎn)生錯誤消息。mysql> select * from lucifer order by age desc limit 2,4;
+------+--------+--------+------+
| id | name | sex | age |
+------+--------+--------+------+
| 1 | xiaowu | female | 21 |
| 1 | xiaoli | male | 20 |
+------+--------+--------+------+
2 rows in set (0.00 sec)
mysql> select * from lucifer limit 2,4 order by age desc;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'order by age desc' at line 1
mysql>
8、什么時候使用引號?
mysql> select * from lucifer where sex = 'female';
+------+-----------+--------+------+
| id | name | sex | age |
+------+-----------+--------+------+
| 1 | xiaoliu | female | 21 |
| 1 | xiaozhang | female | 21 |
| 1 | xiaowu | female | 21 |
+------+-----------+--------+------+
3 rows in set (0.00 sec)
mysql>
mysql> select * from lucifer where age = 20;
+------+--------+------+------+
| id | name | sex | age |
+------+--------+------+------+
| 1 | xiaoli | male | 20 |
+------+--------+------+------+
1 row in set (0.00 sec)
mysql>
9、在 WHERE子句中 AND 和 OR 必須使用圓括號嗎?
AND 和 OR 操作符的 WHERE 子句,都應該使用圓括號明確操作順序。mysql> select * from lucifer where (age = 20 or sex = 'female') and name != 'xiaowu';
+------+-----------+--------+------+
| id | name | sex | age |
+------+-----------+--------+------+
| 1 | xiaoli | male | 20 |
| 1 | xiaoliu | female | 21 |
| 1 | xiaozhang | female | 21 |
+------+-----------+--------+------+
mysql> 3 rows in set (0.00 sec)
10、更新或者刪除表時必須指定 WHERE子 句嗎?
mysql> update lucifer set age = 22 where name = 'xiaoliu';
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> select * from lucifer where name = 'xiaoliu';
+------+---------+--------+------+
| id | name | sex | age |
+------+---------+--------+------+
| 1 | xiaoliu | female | 22 |
+------+---------+--------+------+
1 row in set (0.00 sec)
mysql>
mysql> update lucifer set age = 22;
Query OK, 3 rows affected (0.01 sec)
Rows matched: 4 Changed: 3 Warnings: 0
mysql> select * from lucifer;
+------+-----------+--------+------+
| id | name | sex | age |
+------+-----------+--------+------+
| 1 | xiaoli | male | 22 |
| 1 | xiaoliu | female | 22 |
| 1 | xiaozhang | female | 22 |
| 1 | xiaowu | female | 22 |
+------+-----------+--------+------+
4 rows in set (0.00 sec)
mysql>
11、索引對數(shù)據(jù)庫性能如此重要,應該如何使用它?
通過創(chuàng)建唯一索引可以保證數(shù)據(jù)庫表中每一行數(shù)據(jù)的唯一性。 可以給所有的 MySQL 列類型設置索引。 可以大大加快數(shù)據(jù)的查詢速度,這是使用索引最主要的原因。 在實現(xiàn)數(shù)據(jù)的參考完整性方面可以加速表與表之間的連接。 在使用分組和排序子句進行數(shù)據(jù)查詢時也可以顯著減少查詢中分組和排序的時間
創(chuàng)建和維護索引組要耗費時間,并且隨著數(shù)據(jù)量的增加所耗費的時間也會增加。 索引需要占磁盤空間,除了數(shù)據(jù)表占數(shù)據(jù)空間以外,每一個索引還要占一定的物理空間。如果有大量的索引,索引文件可能比數(shù)據(jù)文件更快達到最大文件尺寸。 當對表中的數(shù)據(jù)進行增加、刪除和修改的時候,索引也要動態(tài)維護,這樣就降低了數(shù)據(jù)的維護速度。
12、盡量使用短索引(前綴索引)
mysql> select * from lucifer;
+------+-----------+--------+------+
| id | name | sex | age |
+------+-----------+--------+------+
| 1 | xiaoli | male | 22 |
| 1 | xiaoliu | female | 22 |
| 1 | xiaozhang | female | 22 |
| 1 | xiaowu | female | 22 |
+------+-----------+--------+------+
4 rows in set (0.00 sec)
mysql> create index idx_lucifer_name on lucifer (name(4));
Query OK, 0 rows affected (0.03 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> show index from lucifer;
+---------+------------+------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
+---------+------------+------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| lucifer | 1 | idx_lucifer_name | 1 | name | A | 1 | 4 | NULL | YES | BTREE | | | YES | NULL |
+---------+------------+------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
1 row in set (0.01 sec)
mysql>
13、MySQL 存儲過程和函數(shù)有什么區(qū)別?
只能通過 return 語句返回單個值或者表對象; 限制比較多,不能用臨時表,只能用表變量,還有一些函數(shù)都不可用等等; 可以嵌入在 SQL 語句中使用,可以在 SELECT 語句中作為查詢語句的一個部分調(diào)用;
不允許執(zhí)行 return,但是可以通過 out 參數(shù)返回多個值; 限制相對就比較少; 一般是作為一個獨立的部分來執(zhí)行;
14、存儲過程中的內(nèi)容可以改變嗎?
15、存儲過程中可以調(diào)用其他存儲過程嗎?
16、存儲過程的參數(shù)不要與數(shù)據(jù)表中的字段名相同。
17、存儲過程的參數(shù)可以使用中文嗎?
18、MySQL 中視圖和表的區(qū)別以及聯(lián)系是什么?
視圖是已經(jīng)編譯好的 SQL 語句,是基于 SQL 語句的結果集的可視化的表,而表不是; 視圖沒有實際的物理記錄,而基本表有; 表是內(nèi)容,視圖是窗口; 表占用物理空間而視圖不占用物理空間,視圖只是邏輯概念的存在,表可以及時對它進行修改,但視圖只能用創(chuàng)建的語句來修改; 視圖是查看數(shù)據(jù)表的一種方法,可以查詢數(shù)據(jù)表中某些字段構成的數(shù)據(jù),只是一些SQL 語句的集合。從安全的角度來說,視圖可以防止用戶接觸數(shù)據(jù)表,因而用戶不知道表結構; 表屬于全局模式中的表,是實表;視圖屬于局部模式的表,是虛表; 視圖的建立和刪除只影響視圖本身,不影響對應的基本表;
19、使用觸發(fā)器時須特別注意!
mysql> create trigger lucifer_tri before insert on lucifer for each row set NEW.id=NEW.id+1;
Query OK, 0 rows affected (0.01 sec)
mysql>
mysql>
mysql> select * from lucifer;
+------+-----------+--------+------+
| id | name | sex | age |
+------+-----------+--------+------+
| 1 | xiaoli | male | 22 |
| 1 | xiaoliu | female | 22 |
| 1 | xiaozhang | female | 22 |
| 1 | xiaowu | female | 22 |
| 1 | lucifer | male | 20 |
| 1 | lucifer | male | 20 |
+------+-----------+--------+------+
6 rows in set (0.00 sec)
mysql> insert into lucifer values(1,'lucifer','male',20);
Query OK, 1 row affected (0.00 sec)
mysql> select * from lucifer;
+------+-----------+--------+------+
| id | name | sex | age |
+------+-----------+--------+------+
| 1 | xiaoli | male | 22 |
| 1 | xiaoliu | female | 22 |
| 1 | xiaozhang | female | 22 |
| 1 | xiaowu | female | 22 |
| 1 | lucifer | male | 20 |
| 1 | lucifer | male | 20 |
| 2 | lucifer | male | 20 |
+------+-----------+--------+------+
7 rows in set (0.00 sec)
BEFORE INSERT 觸發(fā)器,那么如果對表 lucifer 再次創(chuàng)建一個 BEFORE INSERT 觸發(fā)器,MySQL 將會報錯,此時,只可以在表 lucifer 上創(chuàng)建 AFTER INSERT 或者 BEFORE UPDATE 類型的觸發(fā)器。mysql> create trigger lucifer_tri before insert on lucifer for each row set NEW.id=NEW.id+1;
ERROR 1359 (HY000): Trigger already exists
mysql>
20、及時刪除不再需要的觸發(fā)器
mysql> drop trigger lucifer_tri;
Query OK, 0 rows affected (0.03 sec)
mysql>
21、應該使用哪種方法創(chuàng)建用戶?(3種方式)
使用 CREATE USER 語句創(chuàng)建用戶 在 mysql.user 表中添加用戶 使用 GRANT 語句創(chuàng)建用戶(僅限 MySQL 8 版本以下使用)
-- 使用 CREATE USER 語句創(chuàng)建用戶
mysql> create user 'lucifer'@'localhost' identified by 'lucifer';
Query OK, 0 rows affected (0.01 sec)
mysql>
-- 在 mysql.user 表中添加用戶
mysql> select MD5('lucifer');
+----------------------------------+
| MD5('lucifer') |
+----------------------------------+
| cae33a0264ead2ddfbc3ea113da66790 |
+----------------------------------+
1 row in set (0.00 sec)
mysql>
mysql> INSERT INTO mysql.user(Host, User, authentication_string, ssl_cipher, ssuex509_i09_sr, x5ubject) VALUES ('lohoscalt',uci 'lfer MD5('1',lucifer'), '', '',; '')
Query OK, 1 row affected (0.01 sec)
mysql>
-- 使用 GRANT 語句創(chuàng)建用戶
mysql> GRANT SELECT ON*.* TO 'lucifer2'@localhost IDENTIFIED BY 'lucifer';
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'IDENTIFIED BY 'lucifer'' at line 1
mysql>
22、mysqldump 備份的文件只能在 MySQL 中使用嗎?
mysqldump 備份的文本文件實際是數(shù)據(jù)庫的一個副本,使用該文件不僅可以在 MySQL 中恢復數(shù)據(jù)庫,而且通過對該文件的簡單修改,可以使用該文件在 SQL Server 或者 Sybase 等其他數(shù)據(jù)庫中恢復數(shù)據(jù)庫。root@modb:~# mysqldump -uroot -p hr > /root/hr.db
Enter password:
root@modb:~#
root@modb:~# ll hr.db
-rw-r--r-- 1 root root 25327 Nov 26 08:52 hr.db
23、如何選擇備份工具?
熱備(Hot Backup) 冷備(Cold Backup) 溫備(Warm Backup)
表數(shù)據(jù) 二進制日志、InnoDB 事務日志 代碼(存儲過程、存儲函數(shù)、觸發(fā)器、事件調(diào)度器) 服務器配置文件
mysqldump:邏輯備份工具,適用于所有的存儲引擎,支持溫備、完全備份、部分備份、對于 InnoDB 存儲引擎支持熱備。 cp、tar 等歸檔復制工具:物理備份工具,適用于所有的存儲引擎、冷備、完全備份、部分備份。 lvm2 snapshot:借助文件系統(tǒng)管理工具進行備份。 mysqlhotcopy:名不副實的一個工具,僅支持 MyISAM 存儲引擎。 xtrabackup:一款由 percona 提供的非常強大的 InnoDB/XtraDB 熱備工具,支持完全備份、增量備份。
24、平時應該打開哪些日志?
-- 檢查是否開啟慢查詢
mysql> show variables like 'slow_query%';
+---------------------+------------------------------+
| Variable_name | Value |
+---------------------+------------------------------+
| slow_query_log | OFF |
| slow_query_log_file | /var/lib/mysql/modb-slow.log |
+---------------------+------------------------------+
2 rows in set (0.00 sec)
mysql> show variables like 'long_query_time';
+-----------------+-----------+
| Variable_name | Value |
+-----------------+-----------+
| long_query_time | 10.000000 |
+-----------------+-----------+
1 row in set (0.01 sec)
-- 開啟慢查詢?nèi)罩?/span>
mysql> set global slow_query_log='ON';
Query OK, 0 rows affected (0.00 sec)
-- 設置查詢超過10秒就記錄
mysql> set global long_query_time=10;
Query OK, 0 rows affected (0.00 sec)
-- 再次檢查是否開啟
mysql> show variables like 'slow_query%';
mysql> +---------------------+------------------------------+
| Variable_name | Value |
+---------------------+------------------------------+
| slow_query_log | ON |
| slow_query_log_file | /var/lib/mysql/modb-slow.log |
+---------------------+------------------------------+
2 rows in set (0.00 sec)
mysql> show variables like 'general_log%';
+------------------+-------------------------+
| Variable_name | Value |
+------------------+-------------------------+
| general_log | OFF |
| general_log_file | /var/lib/mysql/modb.log |
+------------------+-------------------------+
2 rows in set (0.00 sec)
-- 開啟通用查詢?nèi)罩?/span>
mysql> SET GLOBAL general_log=1;
Query OK, 0 rows affected (0.00 sec)
mysql> show variables like 'general_log%';
+------------------+-------------------------+
| Variable_name | Value |
+------------------+-------------------------+
| general_log | ON |
| general_log_file | /var/lib/mysql/modb.log |
+------------------+-------------------------+
2 rows in set (0.00 sec)
mysql> show variables like 'log_bin%';
+---------------------------------+-----------------------------+
| Variable_name | Value |
+---------------------------------+-----------------------------+
| log_bin | ON |
| log_bin_basename | /var/lib/mysql/binlog |
| log_bin_index | /var/lib/mysql/binlog.index |
| log_bin_trust_function_creators | OFF |
| log_bin_use_v1_row_events | OFF |
+---------------------------------+-----------------------------+
5 rows in set (0.00 sec)
mysql>
25、如何使用二進制日志?
root@modb:/var/lib/mysql# ls binlog*
binlog.000001 binlog.000002 binlog.index
root@modb:/var/lib/mysql# mysqlbinlog binlog.000001 | mysql -u root -p
Enter password:
root@modb:/var/lib/mysql#
26、如何使用慢查詢?nèi)罩荆?/span>
root@modb:/var/lib/mysql# cat /var/lib/mysql/modb-slow.log
/usr/sbin/mysqld, Version: 8.0.26-0ubuntu0.21.04.3 ((Ubuntu)). started with:
Tcp port: 3306 Unix socket: /var/run/mysqld/mysqld.sock
Time Id Command Argument
root@modb:/var/lib/mysql#
long_query_time 的值,可以靈活地掌握不同程度的慢查詢語句。27、是不是索引建立得越多越好?
28、如何使用查詢緩沖區(qū)?
queiy_cache_size 以調(diào)整查詢緩沖區(qū)大小;修改 query_cache_type 以調(diào)整查詢緩沖區(qū)的類型。my.cnf 中修改 query_cache_size 和 query_cache_type 的值如下所示:[mysqld]
query_cache_size= 512M
query_cache_type= 1
query_cache_type=1
SQL_NO_CACHE 關鍵字時,才不會使用查詢緩沖區(qū)。可以使用 FLUSH QUERY CACHE 語句來刷新緩沖區(qū),清理查詢緩沖區(qū)中的碎片。來源:Lucifer三思而后行
推薦閱讀:
MySQL 高級 | 用存儲過程、定時器、觸發(fā)器來解決數(shù)據(jù)分析問題
建議收藏!Python 讀取千萬級數(shù)據(jù)自動寫入 MySQL 數(shù)據(jù)庫

評論
圖片
表情
