mysql進階

隨筆
物化視圖
select user();
select now();
select version();
ifnull
數據庫奔潰後內存沒寫到內存中,重啓時重做

1、視圖

視圖:VIEW
虛表,在調用時保存有實表的查詢結果 ;在調用視圖時進行後臺調用查詢語句進行查詢;可
以當作表來對待;
創建方法:
CREATE VIEW view_name [(column_list)]
AS select_statement [WITH
[CASCADED | LOCAL] CHECK OPTION]
刪除視圖:
DROP VIEW [IF EXISTS]
view_name [, view_name] ...
[RESTRICT | CASCADE]
視圖中的數據事實上存儲於“基表”中,因此,其修改操作也
會針對基表實現;其修改操作受基表限制

擴展:物化視圖是真實存在的表,將查詢結果返回到表中,即存入了磁盤;調用此視圖時的效率比較高,因爲不用進行查詢;實質上是以磁盤空間換取效率的提升;
本點命令:
mysql 登錄無密碼數據庫
show databases;
use hellodb2;
show tables;
select from students
select name,age,gender from students where gender = 'M'
create view view_students as select name,age,gender from students where gender = 'M'
select
from view_students; 創建視圖
update view_students set name='wang' where age=22; 通過視圖修改真正的表
create view view_students1 as select name,age from students where gender='M';
insert view_students1 values('mage',28);
select from view_students1;
select
from students;
desc students; 查看錶students的創建時的描述信息
drop view view_students1;
desc view_students;

2、函數

函數:系統函數和自定義函數
系統函數:
https://dev.mysql.com/doc/refman/5.7/en/func-op-summary-ref.html 先前訪問地址有問
題,要填對;
自定義函數 (user-defined function UDF)
創建和刪除自定義函數語法:
創建UDF:
CREATE [AGGREGATE] FUNCTION function_name(parameter_name type,
[parameter_name type,...])
RETURNS {STRING|INTEGER|REAL} runtime_body
說明: 參數可以有多個,也可以沒有參數
必須有且只有一個返回值
本點常用命令:
select now(); 查看當前系統的時間
select curdate(); 只顯示日期
select curtime(); 只顯示時間
select version(); 查看當前系統的版本
select user(); 查看當前的用戶
select name,ifnull(classid,'noclass') from students; 驗證ifnull函數的用法,classid爲空
就返回noclass,不爲空就返回classid;

3、自定義函數

刪除UDF:
DROP FUNCTION function_name
調用自定義函數語法:
SELECT function_name(parameter_value,...)
示例:創建簡單的無參UDF
CREATE FUNCTION simpleFun() RETURNS VARVHAR(20) RETURN "Hello World!";
本點常用命令:
create function simplefun() returns varchar(20) return "HelloWorld!!"; 創建自定義函數
select simplefun(); 調用自定義函數
create function deleteById(uid smallint unsigned) returns int begin delete from students
where stuid=uid; return (select count(stuid) from students);end// 創建有參數的自定義函數

4、自定義函數

示例: DELIMITER //
CREATE FUNCTION IF EXIST deleteById(uid
SMALLINT UNSIGNED)
RETURNS VARCHAR(20)
BEGIN
DELETE FROM students WHERE stuid = uid;
RETURN (SELECT COUNT(id) FROM students);
END//

5、自定義函數

自定義函數中定義局部變量語法:
DECLARE 變量1[,變量2,... ]變量類型 [DEFAULT 默認值]
說明:局部變量的作用範圍是在BEGIN...END程序中,而且定義局 部變量語句必須在
BEGIN...END的第一行定義
示例:
DELIMITER //
CREATE FUNCTION addTwoNumber(x SMALLINT
UNSIGNED, Y SMALLINT UNSIGNED)
RETURNS SMALLINT
BEGIN
DECLARE a, b SMALLINT UNSIGNED DEFAULT 10;
SET a = x, b = y;
RETURN a+b;
END//

6、自定義函數

爲變量賦值語法:
SET parameter_name = value[,parameter_name = value...]
SELECT INTO parameter_name
示例:
...
DECLARE x int;
SELECT COUNT(id) FROM tdb_name INTO x;
RETURN x;
END//

7、存儲過程

創建存儲過程:
CREATE PROCEDURE sp_name ([ proc_parameter [,proc_parameter ...]])
routime_body
其中:proc_parameter : [IN|OUT|INOUT] parameter_name type
其中IN表示輸入參數,OUT表示輸出參數,INOUT表示既 可以輸入也可以輸出;
param_name表示參數名稱;type表示 參數的類型 ;

8、存儲過程

調用存儲過程:
CALL sp_name ([ proc_parameter [,proc_parameter ...]])
CALL sp_name
說明:當無參時,可以省略"()",當有參數時,不可省略"()”
存儲過程修改:
ALTER語句修改存儲過程只能修改存儲過程的註釋等無關緊 要的東西,不能修改存儲過程體,
所以要修改存儲過程,方法就 是刪除重建;
刪除存儲過程:
DROP PROCEDURE [IF EXISTS] sp_name

9、存儲過程示例

創建無參存儲過程:
delimiter //
CREATE PROCEDURE showTime()
BEGIN
SELECT now();
END//
delimiter ;
CALL showTime;

10、存儲過程示例

創建含參存儲過程:只有一個IN參數
delimiter //
CREATE PROCEDURE seleById(IN id SMALLINT UNSIGNED)
BEGIN
SELECT * FROM students WHERE stuid = id;
END//
delimiter ;
call seleById(2);
此實驗已驗證
11、存儲過程示例

delimiter //
CREATE PROCEDURE dorepeat(p1 INT)
BEGIN
SET @x = 0;
REPEAT SET @x = @x + 1; UNTIL @x > p1 END REPEAT;
END //
delimiter ;
CALL dorepeat(1000);
SELECT @x;

12、存儲過程示例

創建含參存儲過程:包含IN參數和OUT參數
delimiter //
CREATE PROCEDURE deleteById(IN id SMALLINT UNSIGNED, OUT num
SMALLINT UNSIGNED)
BEGIN
DELETE FROM students WHERE stuid = id;
SELETE row_count() into num;
END//
delimiter ;
call seleById(2,@Line);
SELETE @Line;
說明:創建存儲過程deleteById,包含一個IN參數和一個OUT 參數.調用時,傳入刪除的ID和保存
被修改的行數值的用戶變 量@Line,select @Line;輸出被影響行數.

13、存儲過程

存儲過程優勢:
存儲過程把經常使用的SQL語句或業務邏輯封裝起來,預編譯保存在數據庫中,當需要時從數
據庫中直接調用,省去了編譯的過程
提高了運行速度
同時降低網絡數據傳輸量 (用戶通過傳輸函數名和參數進行訪問,數據量變小)
存儲過程與自定義函數的區別:
存儲過程實現的過程要複雜一些,而函數的針對性較強
存儲過程可以有多個返回值,而自定義函數只有一個返回值
存儲過程一般獨立的來執行,而函數往往是作爲其他SQL語句的一部分來使用如select
存儲過程一般用於專職的DBA進行自定義

14、流程控制

存儲過程和函數中可以使用流程控制來控制語句的執行
流程控制:
IF:用來進行條件判斷。根據是否滿足條件,執行不同語句
CASE:用來進行條件判斷,可實現比IF語句更復雜的條件判斷
LOOP:重複執行特定的語句,實現一個簡單的循環
LEAVE:用於跳出循環控制
ITERATE:跳出本次循環,然後直接進入下一次循環
REPEAT:有條件控制的循環語句。當滿足特定條件時,就會跳出循環語句
WHILE:有條件控制的循環語句

15、觸發器

觸發器的執行不是由程序調用,也不是由手工啓動,而是由事件來觸發、 激活從而實現執行
創建觸發器
CREATE
[DEFINER = { user | CURRENT_USER }]
TRIGGER trigger_name
trigger_time trigger_event
ON tbl_name FOR EACH ROW
trigger_body
說明:
trigger_name:觸發器的名稱
trigger_time:{ BEFORE | AFTER },表示在事件之前或之後觸發
trigger_event::{ INSERT |UPDATE | DELETE },觸發的具體事件
tbl_name:該觸發器作用在表名

16、觸發器示例

CREATE TABLE student_info (
stu_no INT(11) NOT NULL AUTO_INCREMENT,
stu_name VARCHAR(255) DEFAULT NULL,
PRIMARY KEY (stu_no)
);
CREATE TABLE student_count (
student_count INT(11) DEFAULT 0
);
INSERT INTO student_count VALUES(0);

17、觸發器示例

示例:創建觸發器,在向學生表INSERT數據時,學生數增加 ,DELETE學生時,學生數減少
CREATE TRIGGER trigger_student_count_insert
AFTER INSERT
ON student_info FOR EACH ROW
UPDATE student_count SET
student_count=student_count+1;

CREATE TRIGGER trigger_student_count_delete
AFTER DELETE ON student_info FOR EACH ROW
UPDATE student_count SET
student_count=student_count-1;

18、觸發器

查看觸發器
SHOW TRIGGERS
查詢系統表information_schema.triggers的方式指定查詢條件,查看指定的觸發器信息。
USE information_schema;
SELECT * FROM triggers WHERE trigger_name='trigger_student_count_insert';
刪除觸發器
DROP TRIGGER trigger_name;

19、MySQL用戶和權限管理

元數據數據庫:mysql
系統授權表:
db, host, user
columns_priv, tables_priv, procs_priv, proxiespriv
用戶賬號:
'USERNAME'@'HOST':
@'HOST':
主機名;
IP地址或Network;
通配符:
%,
: 172.16.%.%

19、用戶管理

創建用戶:CREATE USER
CREATE USER 'USERNAME'@'HOST' [IDENTIFIED BY 'password'];
默認權限:USAGE
用戶重命名:RENAME USER
RENAME USER old_user_name TO new_user_name
刪除用戶:
DROP USER 'USERNAME'@'HOST‘
示例:刪除默認的空用戶
DROP USER ''@'localhost';

20、用戶管理

修改密碼:
mysql>SET PASSWORD FOR 'user'@'host' = PASSWORD(‘password');
mysql>UPDATE mysql.user SET password=PASSWORD('your_password') WHERE
clause; 此方法需要執行下面指令才能生效:mysql> FLUSH PRIVILEGES;
#mysqladmin -u root –poldpass password ‘newpass‘
忘記管理員密碼的解決辦法:
啓動mysqld進程時,爲其使用如下選項:
--skip-grant-tables --skip-networking
使用UPDATE命令修改管理員密碼
關閉mysqld進程,移除上述兩個選項,重啓mysqld

21、MySQL權限管理

權限類別:
數據庫級別
表級別
字段級別
管理類
程序類

22、MySQL用戶和權限管理

管理類:
CREATE TEMPORARY TABLES
CREATE USER
FILE
SUPER
SHOW DATABASES
RELOAD
SHUTDOWN
REPLICATION SLAVE
REPLICATION CLIENT
LOCK TABLES
PROCESS

23、MySQL用戶和權限管理

程序類: FUNCTION、PROCEDURE、TRIGGER
CREATE
ALTER
DROP
EXCUTE
庫和表級別:DATABASE、TABLE
ALTER
CREATE
CREATE VIEW
DROP
INDEX
SHOW VIEW
GRANT OPTION:能將自己獲得的權限轉贈給其他用戶

24、 MySQL用戶和權限管理

數據操作:
SELECT
INSERT
DELETE
UPDATE
字段級別:
SELECT(col1,col2,...)
UPDATE(col1,col2,...)
INSERT(col1,col2,...)
所有權限:ALL PRIVILEGES 或 ALL

25、授權

參考:https://dev.mysql.com/doc/refman/5.7/en/grant.html
GRANT priv_type [(column_list)],... ON [object_type] priv_level TO 'user'@'host' [IDENTIFIED
BY 'password'] [WITH GRANT OPTION];
priv_type: ALL [PRIVILEGES]
object_type:TABLE | FUNCTION | PROCEDURE
priv_level: (所有庫) | . | db_name. | db_name.tbl_name | tbl_name(當前庫的表) |
db_name.routine_name(指定庫的函數, 存儲過程,觸發器)
with_option: GRANT OPTION
| MAX_QUERIES_PER_HOUR count
| MAX_UPDATES_PER_HOUR count
| MAX_CONNECTIONS_PER_HOUR count
| MAX_USER_CONNECTIONS count
示例:GRANT SELECT (col1), INSERT (col1,col2) ON mydb.mytbl TO 'someuser'@'somehost';
本點常用命令:
GRANT SELECT (name), INSERT (age,gender) ON hellodb2.students TO 'test'@'%';
select * from user\G; 豎行查看user表的內容
show grants for 'test'; 顯示用戶test所擁有的權限
26、授權

回收授權:REVOKE priv_type [(column_list)] [, priv_type [(column_list)]] ... ON
[object_type] priv_level FROM user [, user] ... 示例:REVOKE DELETE ON testdb.* FROM
'testuser'@'%‘
查看指定用戶獲得的授權:
Help SHOW GRANTS
SHOW GRANTS FOR 'user'@'host';
SHOW GRANTS FOR CURRENT_USER[()];
注意:MariaDB服務進程啓動時會讀取mysql庫中所有授權表至內存
(1) GRANT或REVOKE等執行權限操作會保存於系統表中,MariaDB的服務進程通常會自動
重讀授權表,使之生效;
(2) 對於不能夠或不能及時重讀授權表的命令,可手動讓MariaDB的服務進程重讀授權表:
FLUSH PRIVILEGES; 重讀授權表以刷新權限
本點常用命令:
revoke select on hellodb2.students from 'test'@'%'; 撤銷授權

27、服務器配置

mysqld選項,服務器系統變量和服務器狀態變量
https://dev.mysql.com/doc/refman/5.7/en/mysqld-option-tables.html
https://mariadb.com/kb/en/library/server-system-variables/
https://mariadb.com/kb/en/library/full-list-of-mariadb-options-system-and-status-variables/
獲取運行中的mysql進程使用各服務器參數及其值
mysql> SHOW GLOBAL VARIABLES;
mysql> SHOW [SESSION] VARIABLES;
注意:其中有些參數支持運行時修改,會立即生效;有些參數不支持,且只能通過修改配置文
件,並重啓服務器程序生效;有些參數作用域是全局的,且不可改變;有些可以爲每個用戶提供
單獨(會話)的設置 ;
本點常用命令:
mysql -e 'show variables;'|wc -l 在數據庫外邊執行查看有多少變量
show variables like 'datadir'; 查看指定變量
show variables like 'log%'; 查看所有以log開頭的變量
show status like 'uptime'; 查看指定狀態變量
變量的類型:選項、系統變量、狀態變量

28、服務器配置

設置服務器系統變量三種方法:
在命令行中設置:
shell> ./mysqld_safe --aria_group_commit="hard“
在配置文件my.cnf中設置:
aria_group_commit = "hard"
在mysql客戶端使用SET命令:
SET GLOBAL aria_group_commit="hard";
常用命令:
/lib/systemd/system/mariadb.service 此文件是啓動服務時的腳本
ExecStart=/usr/bin/mysqld_safe --basedir=/usr 此行是調用safe腳本和選項
vim /usr/bin/mysqld_safe 可以在此加選項進行修改啓動配置

29、服務器端設置

修改服務器變量的值:
mysql> help SET 查看幫助
修改全局變量:僅對修改後新創建的會話有效;對已經建立的會話無效
mysql> SET GLOBAL system_var_name=value;
mysql> SET @@global.system_var_name=value;
修改會話變量:
mysql> SET [SESSION] system_var_name=value;
mysql> SET @@[session.]system_var_name=value;
狀態變量(只讀):用於保存mysqld運行中的統計數據的變量,不可更改
mysql> SHOW GLOBAL STATUS;
mysql> SHOW [SESSION] STATUS;
補充:
打開官網的系統變量標籤頁後如下字符的解釋
dynamic:yes 意味着可以直接修改,不需要將變量寫到文件重啓服務生效
本點常用變量:
系統變量:autocommit、skip_networking、log_bin、skip_name_resolve、
狀態變量:Com_select
本點常用命令:
show status like 'com_select'; 查詢指定狀態變量
show variables like 'port';
mysql -e 'show global status;'|grep Com_select 查詢增長值記錄
mysql -e 'show global status;'|grep Com_insert 查看插入的數量

30、SQL_MODE

服務器變量SQL_MODE:對其設置可以完成一些約束檢查的工作,可分別 進行全局的設置或當前
會話的設置
常見MODE:
NO_AUTO_CREATE_USER
禁止GRANT創建密碼爲空的用戶
NO_AUTO_VALUE_ON_ZERO
在自增長的列中插入0或NULL將不會是下一個自增長值
NO_BACKSLASH_ESCAPES
反斜槓“\”作爲普通字符而非轉義字符
PAD_CHAR_TO_FULL_LENGTH
啓用後,對於CHAR類型將不會截斷空洞數據
PAD_CHAR_TO_FULL_LENGTH
啓用後,對於CHAR類型將不會截斷空洞數據
PIPES_AS_CONCAT
將"||"視爲連接操作符而非“或運算符”
本點常用命令:
create table t1(name char(5)); 建表
set sql_mode='traditional'; 設置模式
insert into t1 values('dsafasfasgsagfsa'); 設置傳統模式後字符長度超出後不能進行
插入,而不只是之前的切斷超出的部分;

31、MySQL架構

圖的詳解:
客戶端用戶通過一個應用程序訪問數據庫,而應用程序則是通過Connectors中的接口進行數
據庫的訪問,其中ODBC 是支持多中應用程序使用的;數據庫服務器有一個連接池用於提供用戶
的連接,並進行驗證;連接池中的線程將已經連接斷開的用戶信息清除後是可以放到連接池進行
重用的;連接池進行併發連接數的限制;連接池進行內存和緩存的檢查;連接成功後就訪問SQL
interface進行SQL語句的接受與識別(語法上);Parser進行SQL語句轉爲二進制並進行權限等
的檢查;Optimizer進行訪問的優化如是否使用索引,選擇最佳路徑等;之後就將請求交給數據庫
的引擎進行正式的訪問;數據庫引擎決定如何存儲查找數據,數據庫引擎也有一個存儲數據的最
小單位block,mysql是每塊16K,是文件系統塊大小的整數倍,在mysql中block大小 只能編譯源
代碼進行修改,而oracle則可以通過重新建立數據庫時用指令進行調整;在文件系統中cache是用
來讀緩存,buffer是寫緩衝區;
32、查詢的執行路徑

解釋:當有人執行過同樣的SQL語句時,就有了緩存信息,直接交給
數據庫引擎進行查詢操作;當沒有人進行查詢過,就進行解析找出好的路徑形成解析樹,然後進過預處理整理形成新的解析樹,然後進行優化處理儘可能找出最佳路徑,然後形成一個執行指令的計劃交給數據庫引擎進行處理;然後將處理的結果進行返回給緩存和客戶端;

33、查詢緩存

查詢緩存( Query Cache )原理:
緩存SELECT操作或預處理查詢的結果集和SQL語句,當有 新的SELECT語句或預處理
查詢語句請求,先去查詢緩存,判斷 是否存在可用的記錄集,判斷標準:與緩存的SQL
語句,是否完 全一樣,區分大小寫 (用哈希值進行比對)
優缺點
不需要對SQL語句做任何解析和執行,當然語法解析必須通 過在先,直接從Query
Cache中獲得查詢結果,提高查詢性能
查詢緩存的判斷規則,不夠智能,也即提高了查詢緩存的使用門檻,降低其效率;
查詢緩存的使用,會增加檢查和清理Query Cache中記錄集 的開銷
注意:查詢的SQL語句要儘可能的規範才能高效的使用查詢緩存;注意查詢緩存的過期
問題;如果查詢緩存沒有被真正的使用起來如更改比較多緩存失效,那麼反而比沒有緩存還
要麻煩;

34、查詢緩存

哪些查詢可能不會被緩存

查詢語句中加了SQL_NO_CACHE參數
使用此參數後查詢不走緩存,對於某些特殊的掃描全表的操作和返回數據
量過大的操作是必要的;此參數通過help select命令可以看到

查詢語句中含有獲得值的函數,包含自定義函數,如:NOW() 、
CURDATE()、GET_LOCK()、RAND()、CONVERT_TZ()等 ;這些獲得值時時刻
刻都在變化,緩存下來馬上就會過期了,沒有緩存的意義;

對系統數據庫的查詢:mysql、information_schema 查詢語句 中使用
SESSION級別變量或存儲過程中的局部變量

查詢語句中使用了LOCK IN SHARE MODE、FOR UPDATE 的語句 查詢語句
中類似SELECT …INTO 導出數據的語句

對臨時表的查詢操作;存在警告信息的查詢語句;不涉及任何表 或視圖的查詢
語句;某用戶只有列級別權限的查詢語句;
如:select now();、select @x;set @x='hello';select @x;

事務隔離級別爲Serializable時,所有查詢語句都不能緩存
事務的隔離級別在後面要講到

35、查詢緩存

查詢緩存相關的服務器變量

show variables like 'query%'; 通過此命令顯示出來數據庫中的變量

query_cache_min_res_unit: 查詢緩存中內存塊的最小分配單位,默 認4k,較小值
會減少浪費,但會導致更頻繁的內存分配操作,較大值 會帶來浪費,會導致碎片過多,
內存不足

query_cache_limit:單個查詢結果能緩存的最大值,默認爲1M,對於查詢結果過
大而無法緩存的語句,建議使用SQL_NO_CACHE

query_cache_size:查詢緩存總共可用的內存空間;單位字節,必須 是1024的整
數倍,最小值40KB,低於此值有警報 ;0默認爲不限制

query_cache_wlock_invalidate:如果某表被其它的會話鎖定,是否仍然可以從查
詢緩存中返回結果, 默認值爲OFF,表示可以在表被其 它會話鎖定的場景中繼續從緩
存返回數據;ON則表示不允許

query_cache_type: 取值爲ON(開啓查詢緩存功能), OFF, DEMAND

參看:https://dev.mysql.com/doc/refman/5.7/en/query-cache-configuration.html

36、查詢緩存

SELECT語句的緩存控制
SQL_CACHE: 顯式指定存儲查詢結果於緩存之中
SQL_NO_CACHE: 顯式查詢結果不予緩存
query_cache_type參數變量:
query_cache_type的值爲OFF或0時,查詢緩存功能關閉
query_cache_type的值爲ON或1時,查詢緩存功能打開, SELECT的結果符合緩存
條件即會緩存,否則,不予緩存, 顯式指定SQL_NO_CACHE,不予緩存,此爲默認值
query_cache_type的值爲DEMAND或2時,查詢緩存功能 按需進行,顯式指定
SQL_CACHE的SELECT語句纔會緩存 ;其它均不予緩存

37、優化查詢緩存

注意:影響命中率(利用查詢緩存的頻率)的各種因數

38、查詢緩存

查詢緩存相關的狀態變量
SHOW GLOBAL STATUS LIKE ‘Qcache%';
Qcache_free_blocks:處於空閒狀態的Query Cache中內存 Block數
Qcache_free_memory:處於空閒狀態的Query Cache 內存總量
Qcache_hits:Query Cache 命中次數;包含下面的新插入的沒有命中的次數
Qcache_inserts:向 Query Cache 中插入新的 Query Cache 的次 數,即沒有命中的次數
Qcache_lowmem_prunes:當 Query Cache 內存容量不夠,需要刪除老的 Query Cache
以給新的 Cache 對象使用的次數
Qcache_not_cached:沒有被 Cache 的 SQL 數,包括無法被 Cache 的 SQL 以及由於
query_cache_type 設置的不會被 Cache 的 SQL語句
Qcache_queries_in_cache:在 Query Cache 中的 SQL 數量
Qcache_total_blocks:Query Cache 中總的 Block

39、命中率

命中率和內存使用率估算
query_cache_min_res_unit ≈(query_cache_size - Qcache_free_memory) /
Qcache_queries_in_cache
查詢緩存命中率 ≈ (Qcache_hits – Qcache_inserts) / Qcache_hits 100%
查詢緩存內存使用率 ≈ (query_cache_size – qcache_free_memory) / query_cache_size
100%

40、InnoDB存儲引擎

InnoDB存儲引擎的緩衝池:
通常InnoDB存儲引擎緩衝池的命中不應該小於99%
查看相關狀態變量:
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_read: 總共讀入的字節數
Innodb_data_reads: 發起讀取請求的次數,每次讀取可能需要讀取多個頁

41、存儲引擎

Innodb緩衝池命中率計算:

42、索引

索引是特殊數據結構:定義在查找時作爲查找條件的字段
優點:提高查詢速度,缺點:佔用額外空間,影響插入速度
索引實現在存儲引擎
索引類型:
聚簇(集)索引、非聚簇索引:數據是否與索引存儲在一起
主鍵索引、輔助索引
稠密索引、稀疏索引:是否索引了每一個數據項 ;樹從上到下依次爲稀疏索引到稠密索引;
B+ TREE、HASH、R TREE 後兩種索引結構用的不多
簡單索引、組合索引(多個 字段組合) 左前綴索引:取前面的字符做索引 覆蓋索引:從索
引中即可取出要查
詢的數據,性能高

43、聚簇和非聚簇索引,主鍵和二級索引

注意:聚簇索引是索引和數據放在一起,而非聚簇索引是索引id按順序存放指向數據,磁盤數據中id爲3可以先存放,然後可以存放id爲1的數據,並不是按照id順序連續空間存放;innodb主鍵會自動創建索引的;二級索引是先找到主鍵索引,然後通過主鍵索引進行數據的查找;MyISAM引擎表是三個文件包括定義文件、索引文件和數據文件;二級索引和主鍵索引的區別是看索引的存放順序和數據的存放順序是否一致;
44、B+TREE索引

45、索引B+tree

46、B-Tree索引

B+ Tree索引:順序存儲,每一個葉子節點到根結點的距離是相同的,如果在某一葉子大量增加
數據要進行數據整理使得樹平衡,B即balance;左前綴索引,適合查詢範圍類的數據如按照字母順序進行排序查找;
可以使用B-Tree索引的查詢類型:
全值匹配:精確所有索引列,如:姓wang,名xiaochun, 年齡30
匹配最左前綴:即只使用索引的第一列,如:姓wang
匹配列前綴:只匹配一列值開頭部分,如:姓以w開頭的
匹配範圍值:如:姓ma和姓wang之間 精確匹配某一列並範圍匹配另一列:如:姓wang,名
以x開 頭的
只訪問索引的查詢 :只以複合索引中的列作爲查詢條件

47、B-Tree索引

B-Tree索引的限制:
如果不從最左列開始,則無法使用索引:如:查找名爲 xiaochun,或姓爲g結尾
不能跳過索引中的列:如:查找姓wang,年齡30的,只能使用索引第一列
如果查詢中某個列是爲範圍查詢,那麼其右側的列都無法 再使用索引:如:姓wang,名x%,
年齡30,只能利用姓和名 上面的索引
特別提示:
索引列的順序和查詢語句的寫法應相匹配,才能更好的利用索引
爲優化性能,可能需要針對相同的列但順序不同創建不同的索引來滿足不同類型的查詢需求

48、Hash索引

Hash索引:基於哈希表實現,只有精確匹配索引中的所有列 的查詢纔有效,索引自身只存儲索引列對應的哈希值和數據指針,索引結構緊湊,查詢性能好
只有Memory存儲引擎支持顯式hash索引
適用場景:
只支持等值比較查詢,包括=, IN(), <=>
不適合使用hash索引的場景:
不適用於順序查詢:索引存儲順序的不是值的順序
不支持模糊匹配
不支持範圍查詢
不支持部分索引列匹配查找:如A,B列索引,只查詢A列索引 無效

49、索引

空間索引(R-Tree):
MyISAM支持空間索引,可以使用任意維度組合查詢,使用特有的函數訪問,常用於做地理
數據存儲,使用不多
全文索引(FULLTEXT):
在文本中查找關鍵詞,而不是直接比較索引中的值,類似搜索 引擎
索引優點:
索引可以降低服務需要掃描的數據量,減少了IO次數
索引可以幫助服務器避免排序和使用臨時表
索引可以幫助將隨機I/O轉爲順序I/O

50、索引

高性能索引策略:
獨立地使用列:儘量避免其參與運算,獨立的列指索引列不能是表達式的一部分,也不能是
函數的參數,在where條件中,始終將索引列單獨放在比較符號的一側
例如:select age from students where age-10 < 20;
左前綴索引:構建指定索引字段的左側的字符數的索引,要通過索引選擇性來評估
索引選擇性:不重複的索引值和數據表的記錄總數的比值;即左側幾個字符已經在表中
能夠唯一的被識別
多列索引:AND操作時更適合使用多列索引,而非爲每個 列創建單獨的索引,即複合索引
選擇合適的索引列順序:無排序和分組時,將選擇性最高 放左側
冗餘和重複索引:(A),(A,B)即爲冗餘索引 不好的索引使用策略,建議擴展索引,而非
冗餘;如擴展索引是有A,還想要B,就刪除A,新建一個AB索引

51、索引優化建議

只要列中含有NULL值,就最好不要在此例設置索引,複合索 引如果有NULL值,此列在使用時也不會使用索引
儘量使用短索引,如果可以,應該制定一個前綴長度
對於經常在where子句使用的列,最好設置索引
對於有多個列where或者order by子句,應該建立複合索引
對於like語句,以%或者‘-’開頭的不會使用索引,以%結尾 會使用索引
儘量不要在列上進行運算(函數操作和表達式操作)
儘量不要使用not in和<>操作
例如:explain select name,age from students where age<>20\G; 不等於20歲的

52、EXPLAIN

通過EXPLAIN來分析索引的有效性:
EXPLAIN SELECT clause
獲取查詢執行計劃信息,用來查看查詢優化器如何執行查詢
例子:explain select name,age from students where age=20\G;
輸出信息說明:
參考 https://dev.mysql.com/doc/refman/5.7/en/explain-output.html
id: 當前查詢語句中,每個SELECT語句的編號
複雜類型的查詢有三種:
簡單子查詢
用於FROM中的子查詢
聯合查詢:UNION
注意:UNION查詢的分析結果會出現一個額外匿名臨時表
例如:select name,age from students union select name,age from teachers;
explain select name,age from students union select name,age from teachers;
常用命令:
create index index_age on students(age); 創建索引
show indexes from students\G; 顯示錶上的所有索引
explain select name,age from students where age=20\G; 查看執行命令中用到的索引
explain select name,age from students where age > 20\G; 不能使用索引
explain select name,age from students where age > 30\G; ???
explain select name,age from students where age between 20 and 30\G; 不能使用索引
create index index_name on students(name);
explain select from students where name like 's%'\G; 可以使用索引
explain select
from students where name like '%g'\G; 不能使用索引
drop index index_name on students; 刪除索引
create index index_name_age on students(name,age); 創建複合索引
explain select from students where name like 'w%'\G; 可以使用第一個索引
explain select
from students where age=20\G; 跨過第一個索引使用第二個是不行的
explain select from students where name like 'w%' and age=20\G; 第一個索引使用了,
第二個沒有使用;
explain select
from students where name='wang' and age=20\G; 第一和第二索引都使
用上了;
explain select name,class from students as s inner join classes as c on
s.classid=c.classid\G; 內連接查詢有兩行,id號同一個
explain select * from students where age > (select age from students where stuid=1)\G;
有子查詢,那麼id號有兩個,查詢有兩行

53、EXPLAIN

select_type: 查詢類型
簡單查詢爲SIMPLE
複雜查詢:
SUBQUERY: 簡單子查詢
PRIMARY:最外面的SELECT
DERIVED: 用於FROM中的子查詢 派生查詢(語句生成的)
例子:explain select from (select from students where gender='M') as a\G; 可以看到
select的類型,如果看不到就要將變量設爲off;先用show variables like '%optimizer%';進行查
詢,然後 set optimizer_switch='derived_merge=off';進行設置,之後在查看就可以了;
UNION:UNION語句的第一個之後的SELECT語句
UNION RESULT: 匿名臨時表
table:SELECT語句關聯到的表

54、EXPLAIN

type:關聯類型或訪問類型,即MySQL決定的如何去查詢表 中的行的方式,以下順序,性能從低到高
ALL: 全表掃描
index:根據索引的次序進行全表掃描;如果在Extra列出現 “Using index”表示了使用覆蓋索
引,而非全表掃描
range:有範圍限制的根據索引實現範圍掃描;掃描位置始於索 引中的某一點,結束於另一

ref: 根據索引返回表中匹配某單個值的所有行
例子:explain select * from students where name= 'wang'\G;
eq_ref:僅返回一個行,但與需要額外與某個參考值做比較
const, system: 直接返回單個行 ;精確匹配
possible_keys:查詢可能會用到的索引
key: 查詢中使用到的索引
key_len: 在索引使用的字節數

55、EXPLAIN

ref: 在利用key字段所表示的索引完成查詢時所用的列或某常 量值
rows:MySQL估計爲找所有的目標行而需要讀取的行數
Extra:額外信息
Using index:MySQL將會使用覆蓋索引,以避免訪問表
Using where:MySQL服務器將在存儲引擎檢索後,再進行 一次過濾
Using temporary:MySQL對結果排序時會使用臨時表
Using filesort:對結果使用一個外部索引排序
注意:set global userstat=1;設置索引使用狀態,然後用show index_statistics;可以查看哪個索引被使用的情況;要索引查詢過後纔有東西

56、管理索引

創建索引:
CREATE INDEX index_name ON tbl_name (index_col_name,...);
help CREATE INDEX
刪除索引:
DROP INDEX index_name ON tbl_name;
查看索引:
SHOW INDEXES FROM [db_name.]tbl_name;
優化表空間:
OPTIMIZE TABLE tb_name 在表進行了大量的修改操作後執行命令進行磁盤的整理

57、SQL語句性能優化

查詢時,能不要就不用,儘量寫全字段名
大部分情況連接效率遠大於子查詢
多表連接時,儘量小表驅動大表,即小表 join 大表
在千萬級分頁時使用limit
對於經常使用的查詢,可以開啓緩存
多使用explain和profile分析查詢語句
查看慢查詢日誌,找出執行時間長的sql語句優化

58、併發控制

鎖粒度:
表級鎖 用戶連接過來修改數據時鎖住整個表防止其它用戶也要修改而產生衝突
行級鎖 鎖住的是一行
鎖:
讀鎖:共享鎖,只讀不可寫,多個讀互不阻塞,
寫鎖:獨佔鎖,排它鎖,一個寫鎖會阻塞其它讀和寫鎖
實現
存儲引擎:自行實現其鎖策略和鎖粒度
服務器級:實現了鎖,表級鎖;用戶可顯式請求 ;自己加是用來解決MyISAM的隔離問題的
分類:
隱式鎖:由存儲引擎自動施加鎖
顯式鎖:用戶手動請求

59、併發控制

鎖策略:在鎖粒度及數據安全性尋求的平衡機制
顯示使用鎖
LOCK TABLES
tbl_name [[AS] alias] lock_type
[, tbl_name [[AS] alias] lock_type] ...
lock_type: READ , WRITE
UNLOCK TABLES 解鎖
FLUSH TABLES tb_name[,...] [WITH READ LOCK]
關閉正在打開的表(清除查詢緩存),通常在備份前加全局讀鎖;可用於緊急寫磁盤;
但是當還有正在讀數據的操作時就不能立馬刷新,要等待讀完才能刷新;可整個系統加鎖
SELECT clause [FOR UPDATE | LOCK IN SHARE MODE]
查詢時加寫或讀鎖
常用命令:
lock tables students read; 給表加讀鎖
update students set name='www' where stuid=28; 加了讀鎖後自己不能寫;其它人寫
時會被阻塞;
unlock tables; 解鎖
lock tables students write; 加寫鎖;自己讀寫都可,別人讀寫都不能
flush tables with read lock; 整個系統全部加鎖,而不是某一個數據庫

60、事務

事務Transactions:一組原子性的SQL語句,或一個獨立工 作單元
事務日誌:記錄事務信息,實現undo,redo等故障恢復功能
ACID特性:
A:atomicity原子性;整個事務中的所有操作要麼全部成 功執行,要麼全部失敗後回滾
C:consistency一致性;數據庫總是從一個一致性狀態轉 換爲另一個一致性狀態
I:Isolation隔離性;一個事務所做出的操作在提交之前, 是不能爲其它事務所見;隔離有多
種隔離級別,實現併發
D:durability持久性;一旦事務提交,其所做的修改會永 久保存於數據庫中
注意:事務日誌是存放在/var/lib/mysql下的ib_logfile0和ib_logfile1文件中的;而數據是存放在相應數據庫下的,如/var/lib/mysql/hellodb2下的students.ibd;建議數據和日誌分開存放;事務的工作示例:第一個事務1、2、3事件都完成,日誌已經在每完成一個事件後寫完,但數據還沒有寫到磁盤;繼續第二個事務1、2完,3還沒做;這時突然系統崩潰;那麼在重新啓動系統時日誌和磁盤數據進行比對,然後第一個事務redo,第二個事務undo;重啓慢有這方面重做事務的原因;

61、Transaction生命週期

注意:事務是不記錄表的查詢操作的,因爲沒有更改;

62、事務

啓動事務:START TRANSACTION
結束事務:
(1) COMMIT:提交 oracle是敲命令進行提交
(2) ROLLBACK: 回滾
注意:只有事務型存儲引擎方能支持此類操作
建議:顯式請求和提交事務,而不要使用“自動提交”功能
set autocommit={1|0}
事務支持保存點:savepoint 加標籤,rollback可以還原到指定點
SAVEPOINT identifier
ROLLBACK [WORK] TO [SAVEPOINT] identifier
RELEASE SAVEPOINT identifier
例子:
insert students(name,age,gender) values('a',20,'M');
insert students(name,age,gender) values('b',30,'M');
select from students;
savepoint ab;
insert students(name,age,gender) values('c',23,'F');
insert students(name,age,gender) values('d',30,'F');
savepoint cd;
insert students(name,age,gender) values('e',38,'F');
select
from students;
rollback to cd;
select from students;
rollback to cd;
rollback to ab;
rollback;
常用命令:
set autocommit=0
update students set name='www' where stuid=28;
select
from students;
commit;
注意:由於事務的隔離級別的限制,當一個用戶修改數據庫的數據時,另一個用戶讀取到的
是原來的數據,而不是正在修改的新數據;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章