MySQL3

MySQL數據庫3

1. 存儲過程

  • 建立存儲過程css

    1. 語法格式
             
             
             
             
             
      • 1
      • 2
      • 3
      CREATE PROCEDURE <==建立存儲過程命令 sp_name([ proc_parameter[,proc_parameter...]]) <==命名存儲過程及參數 routime_body
    2. 說明
      1. routime_body
        符合規定的SQL過程語句,可使用複合語法(例如BEGIN…END),複合語句能夠包含聲明,循環和其餘控制結構語句
      2. proc_parameter
        參數內容分爲[IN|OUT|INOUT] parameter_name type
        其中IN表示輸入參數,OUT表示輸出參數,INOUT表示既能夠輸入也能夠輸出;param_name表示參數名稱;type表示參數的類型
  • 查看存儲過程列表
    SHOW PROCEDURE STATUS
    此內容在mysql自建數據庫information_schema.ROUTINES表中html

  • 查看存儲過程定義
    SHOW CREATE PROCEDURE sp_namemysql

  • 調用存儲過程:web

    1. 有參數調用
      CALL sp_name([ proc_parameter[,proc_parameter…]])
    2. 無參數調用
      CALL sp_name
      說明:當無參時,能夠省略"()",當有參數時,不可省略"()」
    3. 跨數據庫調用
      存儲過程定義是依賴於數據庫的,在哪一個數據庫建立,就在哪一個數據庫使用,在其餘數據庫使用時,要加上數據庫名稱
             
             
             
             
             
      • 1
      MariaDB [db2]> CALL hellodb.showtime;
  • 存儲過程修改
    ALTER語句修改存儲過程只能修改存儲過程的註釋等可有可無的東西,不能修改存儲過程體,因此要修改存儲過程,方法就是刪除重建算法

  • 刪除存儲過程:
    DROP PROCEDURE [IF EXISTS] sp_namesql

  • 示例shell

    1. 建立無參存儲過程:
             
             
             
             
             
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      MariaDB [hellodb]> delimiter // <==修改定界符爲// MariaDB [hellodb]> CREATE PROCEDURE <==建立存儲過程命令 -> showTime() <==定義函數名稱及參數 -> BEGIN <==routime_body複合語法 -> SELECT now(); <==SQL過程語句 -> END// MariaDB [hellodb]> delimiter ; MariaDB [hellodb]> CALL showTime; <==調用存儲過程
    2. 建立含參存儲過程:只有一個IN參數
             
             
             
             
             
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      MariaDB [hellodb]> delimiter // MariaDB [hellodb]> CREATE PROCEDURE -> selectById(IN uid SMALLINT UNSIGNED) <==定義存儲過程名,爲輸入參數名爲uid 類型 -> BEGIN -> SELECT * FROM students WHERE stuid= uid; -> END// MariaDB [hellodb]> delimiter ; MariaDB [hellodb]> call selectById(2);
    3. 在存儲過程當中定義局部變量
             
             
             
             
             
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      MariaDB [hellodb]> delimiter // MariaDB [hellodb]> CREATE PROCEDURE dorepeat(n INT) -> BEGIN -> SET @i= 0; <==定義變量@i -> SET @sum = 0; <==定義變量@i -> REPEAT SET @sum = @sum+@i; SET @i= @i+ 1; <==REPEAT爲重複的意思,相似循環,與結尾的REPEAT成對 -> UNTIL @i> n END REPEAT; <==UNTIL定義結束時間 -> END// MariaDB [hellodb]> delimiter ; MariaDB [hellodb]> CALL dorepeat(100); MariaDB [hellodb]> SELECT @sum; <==查看返回值@sum
    4. 建立含參存儲過程:包含IN參數和OUT參數,OUT能夠將參數傳到mysql中使用
             
             
             
             
             
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      MariaDB [hellodb]> delimiter // MariaDB [hellodb]> CREATE PROCEDURE -> deleteById(IN uid SMALLINT UNSIGNED, OUT num SMALLINT UNSIGNED) -> BEGIN -> DELETE FROM students WHERE stuid= uid; -> SELECT row_count() into num; <==row_count()爲系統函數,記錄刪除行次數 -> END// MariaDB [hellodb]> delimiter ; MariaDB [hellodb]> call deleteById(2,@Line); MariaDB [hellodb]> SELECT @Line;
      說明:建立存儲過程deleteById,包含一個IN參數和一個OUT參數.調用時,傳入刪除的ID和保存被修改的行數值的用戶變量@Line,select@Line;輸出被影響行數
  • 存儲過程優點:數據庫

    1. 存儲過程把常用的SQL語句或業務邏輯封裝起來,預編譯保存在數據庫中,當須要時從數據庫中直接調用,省去了編譯的過程
    2. 提升了運行速度
    3. 同時下降網絡數據傳輸量
  • 存儲過程與自定義函數的區別:vim

    1. 存儲過程實現的過程要複雜一些,而函數的針對性較強
    2. 存儲過程能夠有多個返回值,而自定義函數只有一個返回值
    3. 存儲過程通常獨立的來執行,而函數每每是做爲其餘SQL語句的一部分來使用
  • 流程控制
    存儲過程和函數中可使用流程控制來控制語句的執行api

    1. IF:用來進行條件判斷。根據是否知足條件,執行不一樣語句
    2. CASE:用來進行條件判斷,可實現比IF語句更復雜的條件判斷
    3. LOOP:重複執行特定的語句,實現一個簡單的循環
    4. LEAVE:用於跳出循環控制
    5. ITERATE:跳出本次循環,而後直接進入下一次循環
    6. REPEAT:有條件控制的循環語句。當知足特定條件時,就會跳出循環語句
    7. WHILE:有條件控制的循環語句

2. 觸發器(trigger)

  • 概念
    觸發器的執行不是由程序調用,也不是由手工啓動,而是由事件(對錶的增、刪、改)來觸發、激活從而實現執行

  • 建立觸發器

    1. 語法格式
             
             
             
             
             
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      CREATE [DEFINER = { user | CURRENT_USER }] TRIGGER trigger_name trigger_time <==觸發器的時間 trigger_event <==觸發器的事件 ON tbl_name <==在那張表上 FOR EACH ROW <==針對那一行 trigger_body <==觸發動做
    2. 說明
      1. trigger_name:觸發器的名稱
      2. trigger_time:{ BEFORE | AFTER },表示在事件以前或以後觸發
      3. trigger_event::{ INSERT |UPDATE | DELETE },觸發的具體事件
      4. tbl_name:該觸發器做用在表名
  • 查看觸發器

    1. 在觸發器建立數據庫內輸入
      SHOW TRIGGERS
    2. 查詢系統自建表information_schema.triggers的方式指定查詢條件,查看指定的觸發器信息。
             
             
             
             
             
      • 1
      • 2
      • 3
      MariaDB [db2]> use information_schema; Database changed MariaDB [information_schema]> SELECT * FROM triggers WHERE trigger_name='trigger_student_count_insert'\G
  • 刪除觸發器
    DROP TRIGGER trigger_name;

  • 示例

    1. 建立兩個表student_info和student_count,給student_count設置一個初始值0
             
             
             
             
             
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      '1. 建立表student_info,存放id和姓名,主鍵爲id' MariaDB [db2]> CREATE TABLE student_info( -> stu_id INT(11) NOT NULL AUTO_INCREMENT, -> stu_name VARCHAR(255) DEFAULT NULL, -> PRIMARY KEY (stu_id) -> ); '2. 建立表 student_count,彙總學生數' MariaDB [db2]> CREATE TABLE student_count( -> student_count INT(11) DEFAULT 0 -> ); 3. '爲表 student_count,寫入一個初始值0' MariaDB [db2]> INSERT INTO student_count VALUES(0);
    2. 建立觸發器,在向學生表INSERT數據時,學生數增長,DELETE學生時,學生數減小
             
             
             
             
             
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      1. 增長學員觸發器 MariaDB [db2]> CREATE TRIGGER <==建立命令 -> trigger_student_count_insert <==觸發器名稱 -> AFTER INSERT <==觸發時間 -> ON student_info FOR EACH ROW <==做用在表student_info的每一行 -> UPDATE student_count SET student_count=student_count+1; <==觸發條件 MariaDB [db2]> CREATE TRIGGER trigger_student_count_delete -> AFTER DELETE -> ON student_info FOR EACH ROW -> UPDATE student_count SET student_count=student_count-1;
    3. 增長、刪除學員記錄,驗證觸發器效果
             
             
             
             
             
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      '1. 增長兩條學員信息' MariaDB [db2]> insert student_info values(1,'wang'); Query OK, 1 row affected (0.00 sec) MariaDB [db2]> insert student_info values(2,'mage'); Query OK, 1 row affected (0.01 sec) '2. 查看學員統計表是否自動增長' MariaDB [db2]> select * from student_count; +---------------+ | student_count | +---------------+ | 2 | +---------------+ '3. 刪除學員信息,達成觸發條件' MariaDB [db2]> delete from student_info; Query OK, 2 rows affected (0.00 sec) '4. 查看觸發器效果' MariaDB [db2]> select * from student_count; +---------------+ | student_count | +---------------+ | 0 | +---------------+

3. MySQL用戶和權限管理

3.1 MyAQL用戶

  • 受權表存放位置
    元數據數據庫mysql中系統受權表
    db, host, user
    columns_priv, tables_priv, procs_priv, proxies_priv

  • 建立用戶:

    1. 命令:CREATE USER
    2. 默認權限:USAGE
    3. 語法格式:
      CREATE USER 'USERNAME'@'HOST' [IDENTIFIED BY 'password'];
    4. 示例
      建立用戶v9,容許此用戶在192.168.50.網段的主機登陸本機的數據庫,密碼爲123456
             
             
             
             
             
      • 1
      • 2
      • 3
      MariaDB [db2]> CREATE USER <==建立用戶命令 'v9'@'192.168.50.%' <==定義用戶名,容許登陸主機IP IDENTIFIED BY '123456'; <==建立密碼,IDENTIFIED BY爲定義密碼參數
  • 用戶重命名:

    1. 命令
      RENAME USER
    2. 語法格式
      RENAME USER old_user_name TO new_user_name
  • 刪除用戶:

    1. 方法1,用戶控制命令(在線鏈接的用戶若是沒有任何操做也能夠刪除)
      1. 命令
        DROP USER
      2. 語法格式
        DROP USER ‘USERNAME’@'HOST‘
      3. 示例:刪除安裝系統時的匿名用戶
                 
                 
                 
                 
                 
        • 1
        MariaDB [db2]> DROP USER ''@'localhost'
    2. 方法2,對錶進行操做,刪除對應行,不會當即生效,須要從新載入‘ FLUSH PRIVILEGES’
             
             
             
             
             
      • 1
      • 2
      MariaDB [db2]> DELETE FROM mysql.user WHERE user='v9' AND host='192.168.50.100'; MariaDB [db2]> FLUSH PRIVILEGES <==若是未生效,須要重複文件
  • 修改密碼:

    1. 方法一:用戶控制命令

      1. 語法格式
        SET PASSWORD FOR ‘user’@‘host’ = PASSWORD(‘password’);
      2. 示例
                 
                 
                 
                 
                 
        • 1
        MariaDB [(none)]> SET PASSWORD FOR 'v9'@'192.168.50.100'=password('123456')
    2. 方法二:表操做命令

      1. 語法格式
        UPDATE mysql.user SET password=PASSWORD(‘password’) WHERE clause;
      2. 示例
                 
                 
                 
                 
                 
        • 1
        MariaDB [(none)]> UPDATE mysql.user SET password=password('123') WHERE host='hai7-8';
        此方法若是沒有當即生效,須要執行下面指令:
                 
                 
                 
                 
                 
        • 1
        mysql> FLUSH PRIVILEGES;
    3. 方法三:登陸mysql時,命令行命令

      1. 語法格式
        mysqladmin -u root -poldpassword password ‘newpass‘
      2. 示例
                 
                 
                 
                 
                 
        • 1
        • 2
        • 3
        -p後爲舊密碼,這裏舊密碼爲空,password後爲新密碼 [root@hai7-8 yum.repos.d]$mysqladmin -uroot -p'' password '123456' Enter password: <==輸入舊密碼
  • 忘記管理員密碼的解決辦法:

    1. 修改配置文件,子[mysqld]塊組下,加入skip-grant-tables,從新啓動服務
      –skip-grant-tables <==忽略受權表,也就是登陸不檢查密碼
      –skip-networking <==忽略網絡功能,即斷開網絡,避免其餘用戶遠程登陸
    2. 重啓服務後,進入mysql後,使用UPDATE命令修改管理員密碼
             
             
             
             
             
      • 1
      • 2
      MariaDB [(none)]> update mysql.user set password=''; <==實驗環境,這裏就設爲空密碼了 MariaDB [(none)]> FLUSH PRIVILEGES; <==將修改生效
    3. 關閉mysqld進程,移除配置文件中skip-grant-tables項,重啓服務

3.2 MyAQL權限管理

  • 權限類別

    1. 管理類
權限 描述
CREATE TEMPORARY TABLES 建立臨時表權限
CREATE USER 建立用戶權限
FILE 文件訪問權限
SUPER 執行kell線程權限
SHOW DATABASES 查看數據庫權限
RELOAD 執行flush-hosts, flush-logs, flush-privileges, flush-status, flush-tables, flush-threads, refresh, reload等命令的權限
SHUTDOWN 關閉數據庫權限
REPLICATION SLAVE 複製權限
REPLICATION CLIENT 複製權限
LOCK TABLES 鎖表權限
PROCESS 查看進程權限
  1. 程序類:FUNCTION、PROCEDURE、TRIGGER
權限 描述
CREATE 建立數據庫、表或索引權限
ALTER 更改表權限
DROP 刪除數據庫或表權限
EXCUTE 執行存儲過程權限
  1. 數據庫和表級別:DATABASE、TABLE
權限 描述
ALTER 更改表權限
CREATE 建立數據庫、表或索引權限
CREATE VIEW 建立視圖權限
DROP 刪除數據庫或表權限
INDEX 索引權限
SHOW VIEW 查看視圖權限
GRANT OPTION 能將本身得到的權限轉贈給其餘用戶
  1. 數據操做:
權限 描述
SELECT 查詢權限
INSERT 插入權限
DELETE 刪除數據權限
UPDATE 更新權限
  1. 字段級別:
權限 描述
SELECT(col1,col2,…) 指定字段查詢權限
UPDATE(col1,col2,…) 指定字段更新權限
INSERT(col1,col2,…) 指定字段插入權限
  1. 全部權限:ALL PRIVILEGES 或ALL

3.3 受權操做

參考:https://dev.mysql.com/doc/refman/5.7/en/grant.html

  • 受權指令 GRANT
    1. 語法格式
      GRANT priv_type[(column_list)],… ON [object_type] priv_levelTO ‘user’@‘host’ [IDENTIFIED BY ‘password’] [WITH GRANT OPTION];

    2. 說明

      1. priv_type
        權限類別: 例如ALL [PRIVILEGES]
      2. (column_list)
        針對於哪一列進行受權
      3. ON:表示將在哪一個對象上實施受權
      4. object_type
        實施對象,要指明庫名(TABLE| FUNCTION | PROCEDURE)
      5. priv_level
        權限級別: *(全部庫) | *.* | db_name.* | db_name.tbl_name| tbl_name(當前庫的表) | db_name.routine_name(指定庫的函數,存儲過程,觸發器)
      6. [IDENTIFIED BY ‘password’]
        設置密碼,建立用戶受權一塊兒操做時使用
      7. with_option(受權的特殊選項)
        1. GRANT OPTION:運行將權限受權給他人
        2. MAX_QUERIES_PER_HOUR count:限定在每小時能夠查詢的次數
        3. MAX_UPDATES_PER_HOUR count:最多更新多少次
        4. MAX_CONNECTIONS_PER_HOUR count:最多鏈接次數
        5. MAX_USER_CONNECTIONS count:受權用戶的最大鏈接數
    3. 示例
      受權用戶v9@'192.168.50.100’能夠對 hellodb數據庫中students表查詢id和name的權限

           
           
           
           
           
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      MariaDB [hellodb]> grant select(stuid,name) on hellodb.students to v9@'192.168.50.100' '在192.168.50.100主機上使用帳號v9查看授予的權限' MariaDB [hellodb]> desc students; +-------+------------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------+------------------+------+-----+---------+----------------+ | StuID | int(10) unsigned | NO | PRI | NULL | auto_increment | | Name | varchar(50) | NO | | NULL | | +-------+------------------+------+-----+---------+----------------+

      受權而且建立帳號

           
           
           
           
           
      • 1
      MariaDB [(none)]> grant all on *.* to v9@'192.168.50.109' IDENTIFIED BY '123456';
  • 回收權限指令 REVOKE
    1. 語法格式
           
           
           
           
           
      • 1
      • 2
      • 3
      • 4
      REVOKE priv_type[(column_list)] [ , priv_type[(column_list)]] ... ON [object_type] priv_level FROM user [, user] ...
    2. 示例
      回收用戶 v9@'192.168.50.100’在數據庫hellodb中students表上的查看字段stuid,name的權限
           
           
           
           
           
      • 1
      • 2
      • 3
      MariaDB [(none)]> REVOKE SELECT (stuid,name) -> ON `hellodb`.`students` -> FROM v9@'192.168.50.100';
  • 查看指定用戶得到的受權:
    1. 使用幫助
      Help SHOW GRANTS
    2. 查詢指定用戶權限
      1. 語法格式
        SHOW GRANTS FOR ‘user’@‘host’;
      2. 示例
               
               
               
               
               
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        MariaDB [hellodb]>SHOW GRANTS FOR v9@'192.168.50.100'; +----------------------------------------------------------------------------------------------------------------+ | GRANT USAGE ON *.* TO 'v9'@'192.168.50.100' IDENTIFIED BY PASSWORD '*6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9' | 鏈接權限 | GRANT SELECT (name, stuid) ON `hellodb`.`students` TO 'v9'@'192.168.50.100' 查詢權限 | +----------------------------------------------------------------------------------------------------------
    3. 查看當前用戶的權限
      SHOW GRANTS FOR CURRENT_USER[()];
    4. 注意項
      MariaDB服務進程啓動時會讀取mysql庫中全部受權表至內存
      1. GRANT或REVOKE等執行權限操做會保存於系統表中,MariaDB的服務進程一般會自動重讀受權表,使之生效
      2. 對於不可以或不能及時重讀受權表的命令,可手動讓MariaDB的服務進程重讀受權表:mysql> FLUSH PRIVILEGES;
      3. 回收受權,或者受權其餘權限後,用戶須要從新登陸才能夠生效

4. 存儲引擎

4.1 從功能模塊看MySQL體系結構

在這裏插入圖片描述

  • 各模塊說明
    1. 初始化模塊
      MySQL啓動的時候,對整個系統作各類各樣的初始化操做,好比各類buffer,cache結構的初始化和內存空間的申請,各類系統變量、存儲引擎的初始化設置等

    2. 鏈接管理模塊
      負責管理遠程鏈接用戶請求,接收鏈接請求,轉發全部鏈接請求到線程管理模塊

    3. 線程管理模塊
      管理MYsQl的多個線程,負責爲鏈接用戶分配一個線程單獨服務以及回收退出用戶的空閒線程,回收的線程能夠重複使用

    4. 用戶模塊
      用戶帳號管理,主要包括用戶的登陸鏈接權限控制和用戶的受權管理

    5. 命令分發器:
      在MySQL中咱們習慣將全部的Client端發送給Server端的命令都稱爲query,服務線程收到客戶端的query後,傳遞給專門負責將各類query進行分類而後轉發給各個對應的處理模塊,這個模塊就是命令分發器,主要工做就是講query語句進行語義和語法的分析,而後按不一樣的操做類型進行分類,而後作針對性的轉發

    6. 查詢緩存模塊
      將客戶端提交的SELECT類query請求的返回結果cache到內存中,與此quer的一個hash值作對應,此query所去數據的基表發生任何數據變化後,MySQL會自動使此query的cache失效,查詢緩存模塊對性能的提升很是顯著,相對的對內存的消耗也很是大

    7. 日誌記錄模塊
      負責真個系統級別的邏輯層的日誌記錄,包括error log, binary log,slow query log等

    8. 命令解析器
      非查詢命令經過命令發生器,發送到命令解析器上,再分發到對應的模塊中進行管理

    9. 查詢優化器:
      根據客戶端請求的query語句,和數據庫中的一些統計信息,在一系列算法的基礎上進行分析,得出最有策略,告訴後面的程序如何取得query語句的結果

    10. 表變動模塊
      負責完成一些DML和DDL的query,如:updatedelteinsertcreate tablealter table等語句的處理

    11. 表維護模塊
      表的狀態監測,錯誤修復,以及優化和分析等工做

    12. 複製模塊
      分爲Master模塊和Slave模塊兩部分,Master模塊主要負責在replication環境中讀取Master端的binary日誌,以及與slave端的I/O線程交互等工做。Slave模塊負責從Master端請求和接收binary日誌,並寫入本地relay log中的I/O線程,還要負責從relay log中讀取相關日誌文件,而後解析成能夠在Slave端正確執行並獲得和Master端徹底相同的結果的命令並交給slave執行的SQL線程

    13. 狀態模塊
      負責在客戶端請求系統狀態的時候,將各類張貼數據返回給用戶,像DBA經常使用的各類show status命令,show variables命令等,所獲得的結果都是這個模塊返回的

    14. 訪問控制模塊:
      根據用戶模塊中各用戶的受權信息,以及數據庫自身特有的各類約束,來控制用戶對數據的訪問

    15. 表管理模塊
      維護表的定義文件(也就是*.frm文件)、表結構信息cache、table級別的鎖管理

    16. 存儲引擎接口模塊:
      決定了將用戶數據如何保存到物理設備上

    17. 網絡交互模塊
      底層網絡交互模塊,抽象出底層網絡交互所使用的接口api,實現底層網絡數據的接收與發送,以方便其餘各個模塊調用,以及對這一部分的維護,全部源代碼都在vio文件夾下面

    18. 核心API
      提供須要很是高效的底層操做功能優化實現,包括各類底層數據結構的實現,特殊算法的實現,字符串處理,數字處理等,小文件I/O,格式化輸出,以及內存管理;API模塊的全部源代碼集中在mysys和strings文件夾下

4.2 存儲引擎

在這裏插入圖片描述

  • 數據庫特徵說明
    1. srorage limits
      最大存儲
    2. Transactions:
      事務,多個操做做爲一個總體出現
    3. Locking granularity
      鎖,避免同時操做,帶來不可預期的結果
    4. MVCC:
      1. 做用
        多版本併發控制機制,在一個數據庫中可能有多個事務同時訪問一個資源,若是沒有控制機制,極可能出現髒數據,MVCC控制機制能夠解決此問題
      2. 原理
        在數據庫中的表,系統會增長兩個隱藏字段insert 和delete,分別記錄行數據建立和刪除時的版本號,此版本號是隨事務的建立而不斷增加的數字,在事務開始時會記錄它本身的系統版本號,後來的事務只會比以前的事務編號大
        事務對錶作出insert操做時,會在insert字段增長作此操做事務的編號,delete會在刪除字段增長編號,修改會同時在insert和delete字段增長編號。
      3. 事務DELECT表時,獲得的數據
        1. 必須找到一個行的版本,它至少要和事務的版本同樣老(也即它的版本號不大於事務的版本號)。這保證了無論是事務開始以前,或者事務建立時,或者修改了這行數據的時候,這行數據是存在的。
        2. 這行數據的刪除版本必須是未定義的或者比事務版本要大。這能夠保證在事務開始以前這行數據沒有被刪除。這裏的不是真正的刪除數據,而是標誌出來的刪除。真正意義的刪除是在commit的時候。
    5. Geospatial data type support
      地理空間數據類型支持
    6. Geospatial indexing support
      地理空間索引支持
    7. B-tree indexes:B-tree索引
      全部的索引節點都按照balance tree的數據結構來存儲,全部的索引數據節點都在葉節點
    8. T-tree indexes:T-tree 索引
    9. Hash indexes:哈希索引
    10. Full-text search indexes:全文索引
    11. Clustered indexes:彙集索引
    12. Data caches:數據緩存,將表內的數據放在內存中,讓用戶直接使用
    13. index caches:索引緩存
    14. Compressed data:壓縮數據
    15. Encrypted data:加密數據
    16. Cluster database support:集羣數據庫支持
    17. Replication support:複製支持
    18. Foreign key support :外鍵支持
    19. Backup/point-in-time recovery:備份實時恢復
    20. Query cache support:查詢緩存支持

4.3 MyISAM引擎

  • 特色

    1. 不支持事務,操做只能一步一步執行,若是在執行過程當中出現故障,很難保證數據的完整性和一致性
    2. 表級鎖定,影響併發操做
    3. 讀寫相互阻塞,寫入不能讀,讀時不能寫
    4. 只緩存索引
    5. 不支持外鍵約束
    6. 不支持聚簇索引
    7. 讀取數據較快,佔用資源較少
    8. 不支持MVCC(多版本併發控制機制)高併發
    9. 崩潰恢復性較差
    10. MySQL5.5.5前默認的數據庫引擎
  • 適用場景
    只讀(或者寫較少)、表較小(能夠接受長時間進行修復操做)

  • 支持索引類型

    1. B-TREE索引
      是參與一個索引的全部字段的長度之和不能超過1000 字節
    2. R-TREE索引
      主要設計用於爲存儲空間和多
      維數據的字段作索引,因此目前的MySQL 版原本說,也僅支持geometry 類型的字段做索引。
    3. Full-text 索引
      Full-text 索引就是咱們長說的全文索引,他的存儲結構也是b-tree。主要是爲了
      解決在咱們須要用like 查詢的低效問題
  • MyISAM數據庫文件存放
    對於每個表對應有三個文件,存放在所屬數據庫的文件夾下

    1. tbl_name.frm:
      與表相關的元數據信息,包括表結構的定義信息
    2. tbl_name.MYD:
      存放表數據的文件
    3. tbl_name.MYI:
      存放索引相關信息文件

4.4 InnoDB引擎

  • 特色:
    1. 鎖定集中的改進,行級鎖,經過索引來完成
    2. 支持事務,適合處理大量短時間事務,innodb引擎最重要的一點
    3. 讀寫阻塞與事務隔離級別相關
    4. 可緩存數據和索引
    5. 實現外鍵約束
      Innodb 實現了外鍵引用這一數據庫的重要特性,使在數據庫端控制部分數據的完整性成爲可能。
    6. 支持聚簇索引
    7. 崩潰恢復性更好
    8. 支持MVCC高併發
    9. 從MySQL5.5後支持全文索引
    10. 從MySQL5.5.5開始爲默認的數據庫引擎
  • InnoDB數據庫文件
    1. 兩類文件放在數據庫獨立目錄中
      1. 數據文件(存儲數據和索引):tb_name.ibd
      2. 表格式定義:tb_name.frm
    2. 全部InnoDB表的數據和索引放置於同一個表空間中
      表空間文件:datadir定義的目錄下
      數據文件:ibddata1, ibddata2, …
    3. 設置每一個表單獨使用一個表空間存儲表的數據和索引
      啓用:innodb_file_per_table=ON(MariaDB5.5之後版本默認開啓)
      參看:https://mariadb.com/kb/en/library/xtradbinnodb-server-system-variables/#innodb_file_per_table
  • MySQL中的系統數據庫使用的引擎
    1. mysql數據庫
      是mysql的核心數據庫,相似於sql server中的master庫,主要負責存儲數據庫的用戶、權限設置、關鍵字等mysql本身須要使用的控制和管理信息
           
           
           
           
           
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      '查看mysql數據庫中文件的結構' MariaDB [(none)]> show table status from mysql\G *************************** 30. row *************************** Name: user Engine: MyISAM <==存儲引擎爲 MyISAM Version: 10 Row_format: Dynamic ......省略 Comment: Users and global privileges
    2. PERFORMANCE_SCHEMA數據庫
      MySQL 5.5開始新增的數據庫,主要用於收集數據庫服務器性能參數(例如鏈接狀況、負載狀況),庫裏表的存儲引擎均爲PERFORMANCE_SCHEMA,用戶不能建立存儲引擎爲PERFORMANCE_SCHEMA的表
           
           
           
           
           
      • 1
      • 2
      • 3
      • 4
      MariaDB [(none)]> show table status from performance_schema\G *************************** 52. row *************************** Name: users Engine: PERFORMANCE_SCHEMA
    3. information_schema數據庫
      MySQL 5.0以後產生的,一個虛擬數據庫,物理上並不存在。information_schema數據庫相似與「數據字典」,提供了訪問數據庫元數據的方式,即數據的數據。好比數據庫名或表名,列類型,訪問權限(更加細化的訪問方式),使用的存儲引擎爲MEMORY
           
           
           
           
           
      • 1
      • 2
      • 3
      • 4
      MariaDB [(none)]> show table status from information_schema\G *************************** 75. row *************************** Name: INNODB_SYS_SEMAPHORE_WAITS Engine: MEMORY

4.5 其它存儲引擎

  • Performance_Schema
    mysql自建數據庫 performance_schema使用的引擎
  • Memory
    將全部數據存儲在RAM中,以便在須要快速查找參考和其餘相似數據的環境中進行快速訪問。適用存放臨時數據,之前被稱爲HEAP引擎
  • MRG_MyISAM
    使MySQL DBA或開發人員可以對一系列相同的MyISAM表進行邏輯分組,並將它們做爲一個對象引用。適用於VLDB(Very Large Data Base)環境,如數據倉庫
  • Archive
    爲存儲和檢索大量不多參考的存檔或安全審覈信息,只支持SELECT和INSERT操做;支持行級鎖和專用緩存區
  • Federated聯合
    用於訪問其它遠程MySQL服務器一個代理,它經過建立一個到遠程MySQL服務器的客戶端鏈接,並將查詢傳輸到遠程服務器執行,然後完成數據存取,提供連接單獨MySQL服務器的能力,以便從多個物理服務器建立一個邏輯數據庫。很是適合分佈式或數據集市環境
  • BDB
    可替代InnoDB的事務引擎,支持COMMIT、ROLLBACK和其餘事務特性
  • Cluster/NDB
    MySQL的簇式數據庫引擎,尤爲適合於具備高性能查找要求的應用程序,這類查找需求還要求具備最高的正常工做時間和可用性,主要用於MySQL Cluster 分佈式集羣環境,
  • CSV
    CSV存儲引擎使用逗號分隔值格式將數據存儲在文本文件中。可使用CSV引擎以CSV格式導入和導出其餘軟件和應用程序之間的數據交換
  • BLACKHOLE
    -黑洞存儲引擎接受但不存儲數據,檢索老是返回一個空集。做爲中間代理使用,該功能可用於分佈式數據庫設計,數據自動複製,但不是本地存儲,例如用於主從複製的中間代理
  • example
    「stub」引擎,它什麼都不作。可使用此引擎建立表,但不能將數據存儲在其中或從中檢索。目的是做爲例子來講明如何開始編寫新的存儲引擎

4.6 管理存儲引擎

  • 查看mysql支持的存儲引擎:
    show engines;

  • 查看當前默認的存儲引擎:

       
       
       
       
       
    • 1
    MariaDB [(none)]> SHOW VARIABLES LIKE '%storage_engine%'
  • 設置默認的存儲引擎:

       
       
       
       
       
    • 1
    • 2
    • 3
    vim /etc/my.conf [mysqld] default_storage_engine=InnoDB <==[mysqld]中增長系統此選項
  • 查看庫中全部表使用的存儲引擎
    Show table status from db_name;

       
       
       
       
       
    • 1
    • 2
    '查看hellodb數據庫中表的引擎' MariaDB [(none)]> SHOW table STATUS FROM hellodb\G
  • 查看庫中指定表的存儲引擎

    1. 經過查看錶狀態信息獲取
      show table status like ’ tb_name’;
           
           
           
           
           
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      '進入表所在數據庫' MariaDB [(none)]> use hellodb '查詢表students所用引擎' MariaDB [hellodb]> SHOW table STATUS LIKE 'students'\G *************************** 1. row *************************** Name: students 'Engine: InnoDB' <==存儲引擎
    2. 經過查看錶建立信息獲取
      show create table tb_name;
           
           
           
           
           
      • 1
      • 2
      • 3
      MariaDB [hellodb]> SHOW CREATE table students; ......省略 ) 'ENGINE=InnoDB' AUTO_INCREMENT=26 DEFAULT CHARSET=utf8 |
  • 設置表的存儲引擎:

    1. 建立表時,指定存儲引擎
      CREATE TABLE tb_name(… ) ENGINE=InnoDB;
           
           
           
           
           
      • 1
      • 2
      '建立默認引擎爲Innodb的表cc' MariaDB [db2]> CREATE TABLE cc(StuID int unsigned NOT NULL,Name varchar(50) NOT NULL) ENGINE=Innodb;
    2. 修改表存儲引擎
      ALTER TABLE tb_name ENGINE=InnoDB;
           
           
           
           
           
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      '修改表cc的存儲引擎爲MyISAM' MariaDB [db2]> ALTER TABLE cc ENGINE=MyISAM; '查看修改效果' MariaDB [db2]> SHOW TABLE STATUS LIKE 'cc'\G *************************** 1. row *************************** Name: cc Engine: MyISAM

5. 服務器配置

  • mysql官方服務器配置表

    1. 官方地址
      https://dev.mysql.com/doc/refman/5.7/en/mysqld-option-tables.html
    2. 配置表格式
      在這裏插入圖片描述
    3. 標準表內容
      1. Cmd-Linev
        是否能夠在命令行執行
      2. Option file
        服務器選項,能夠寫在配置文件中,一般來說鏈接符使用’-’,因爲不少服務器選項同時也爲變量因此也支持‘_’寫法
      3. System Var
        是否能夠作服務器變量,鏈接符使用’_’,能夠用做臨時修改,修改又分爲Global(不論鏈接多少會話都有效)和Session(針對當前會話有效)級別,Both表示兩個都支持
      4. Status Var
        狀態變量,做爲值來參考,不能夠修改
      5. Dynamic
        是否支持動態,在不重啓主機的狀況下直接修改
  • mariadb官方服務器配置列表

    1. 官方地址
      https://mariadb.com/kb/en/library/full-list-of-mariadb-options-system-and-status-variables/
    2. 格式
      --aria-block-size:帶–表示爲服務器選項,
      aria_block_size:表示同時爲變量
      在這裏插入圖片描述 點擊藍色部分,進入詳細描述
           
           
           
           
           
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      aria_block_size <==配置選項|變量 Description: Block size to be used for Aria index pages. Changing this requires dumping, deleting old tables and deleting all log files, and then restoring your Aria tables. If key lookups take too long (and one has to search roughly 8192/2 by default to find each key), can be made smaller, e.g. 2048 or 4096. Commandline: --aria-block-size=# <==是否支持命令行 Scope: Global <==變量範圍級別 Dynamic: No <==是否支持動態修改 Data Type: numeric <==數據類型 Default Value: 8192 <==默認值
  • 系統變量

    1. 系統變量查詢

      1. 格式
        支持模糊查詢,默認爲SESSION級別的
        SHOW VARIABLES [LIKE 'Variable_name']
        查GLOBAL級別的變量
        SHOW GLOBAL VARIABLES [LIKE 'Variable_name]'
      2. 示例
               
               
               
               
               
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        '列出全部會話系統變量' MariaDB [(none)]> SHOW VARIABLES; '查找指定會話系統變量' MariaDB [(none)]>SHOW VARIABLESlike LIKE '%datadir%' ; +---------------+--------------+ | Variable_name | Value | +---------------+--------------+ | datadir | /data/mysql/ | <==變量的鍵值 +---------------+--------------+
      3. 常見的系統變量
        max_connections:容許最大併發鏈接數
               
               
               
               
               
        • 1
        • 2
        MariaDB [hellodb]> show variables like '%connect%'; | max_connections | 151 |
    2. 修改服務器變量的值:

      1. 獲取設置SET幫助
        mysql> help SET
      2. 修改全局變量:僅對修改後新建立的會話有效;對已經創建的會話無效
        SET GLOBAL system_var_name=value
        SET @@global.system_var_name=value
               
               
               
               
               
        • 1
        • 2
        MariaDB [db2]> SET GLOBAL max_connections=500; MariaDB [db2]> SET @@GLOBAL.max_connections=600;
      3. 修改會話變量:
        SET [SESSION] system_var_name=value
        SET @@[session.] system_var_name=value
  • 狀態變量(只讀)
    用於保存mysqld運行中的統計數據的變量,不可更改

    1. 格式
      查看全局狀態變量
      SHOW GLOBAL STATUS [LIKE ‘Variable_name’]
      查看會話狀態變量
      SHOW [SESSION] STATUS [LIKE ‘Variable_name’]

    2. 示例
      uptime:查看服務器啓動時間

           
           
           
           
           
      • 1
      MariaDB [(none)]> show status like 'uptime';

      Com_select:查看使用查詢的次數

           
           
           
           
           
      • 1
      • 2
      MariaDB [hellodb]> show status like '%select%'; | Com_select | 4 | <==查詢計數器

      Com_insert:查看插入計數器

           
           
           
           
           
      • 1
      • 2
      MariaDB [hellodb]> show status like '%insert%'; | Com_insert | 1 |

      Threads_connected:查看多少人正在鏈接數據庫,Threads爲進程項

           
           
           
           
           
      • 1
      • 2
      • 3
      MariaDB [hellodb]> show status like '%Threads%'; | Threads_connected | 1 | <==正在鏈接的 | Threads_running | 1 | <==正在運行的
  • 服務器選項

    1. 查看服務器選項
      獲取mysqld的可用選項列表
           
           
           
           
           
      • 1
      [root@hai7-8 mysql]$mysqld --verbose --help
      獲取默認設置
           
           
           
           
           
      • 1
      [root@hai7-8 mysql]$mysqld --print-defaults
      若是mysqld不在PATH變量中,須要寫絕對路徑
           
           
           
           
           
      • 1
      • 2
      • 3
      • 4
      • 5
      查看進程,找到服務絕對路徑 [root@hai7-8 ~]$ps aux|grep mysqld [root@hai7-8 ~]$/usr/libexec/mysqld --verbose --help 獲取默認設置 [root@hai7-8 ~]$/usr/libexec/mysqld --print-defaults
    2. 設置服務器選項方法
      1. 在命令行中設置:
        [root@hai7-8 ~]$./mysqld_safe –-skip-name-resolve=1;
      2. 在配置文件my.cnf中設置:
               
               
               
               
               
        • 1
        • 2
        • 3
        [root@hai7-8 ~]$vim /etc/my.cnf [mysqld] skip_name_resolve=1 <==增長在mysqld塊裏
    3. 示例
      設置默認將表數據獨立存放爲單個文件
           
           
           
           
           
      • 1
      • 2
      • 3
      vim /etc/my.conf [mysqld] innodb_file_per_table
      拒絕將ip地址反向解析成名字
      將ip地址反向解析成名字可能會致使鏈接失敗,例如集羣操做時
           
           
           
           
           
      • 1
      • 2
      • 3
      vim /etc/my.conf [mysqld] skip-name-resolve=on <==便是選項又是變量
  • 服務器變量SQL_MODE

    1. 做用
      對其設置能夠完成一些約束檢查的工做,可分別進行全局的設置或當前會話的設置,參看:https://mariadb.com/kb/en/library/sql-mode/
    2. 常見MODE:
      1. NO_AUTO_CREATE_USER
        禁止GRANT(受權)建立密碼爲空的用戶
      2. NO_ZERO_DATE
        在嚴格模式,不容許使用‘0000-00-00’的時間
      3. ONLY_FULL_GROUP_BY
        對於GROUP BY聚合操做,若是在SELECT中的列,沒有在GROUP BY中出現,那麼將認爲這個SQL是不合法的
      4. NO_BACKSLASH_ESCAPES
        反斜槓「\」做爲普通字符而非轉義字符
      5. PIPES_AS_CONCAT
        將"||"視爲鏈接操做符而非「或運算符」
  • 注意事項

    1. 其中有些參數支持運行時修改,會當即生效;有些參數不支持,且只能經過修改配置文件,並重啓服務器程序生效;有些參數做用域是全局的,且不可改變;有些能夠爲每一個用戶提供單獨(會話)的設置
    2. 純變量不能放在配置文件中的,會影響啓動,例如character_set_results

6. 查詢緩存

  • 從工做流程看MySQL架構
    數據庫自己是不能和磁盤直接交流的,是經過存儲引擎將指令發送給內核,經過內核和文件系統打交道,再將數據寫到磁盤文件中
    在這裏插入圖片描述

    1. connectors
      各類語言提供的鏈接數據庫的能力
    2. connection pool
      數據庫中的鏈接池,提供了驗證身份,線程複用(系統判斷線程使用次數過多,自動銷燬),鏈接限制,內存檢查,緩存功能使用
    3. SQL interface
      將用戶提交的SQL語句進行檢查,經過檢查,則將SQL語句翻譯給系統,進行執行
    4. parser
      解析語句,驗證訪問對象權限
    5. optimizer
      優化過程,訪問路徑
    6. Caches & Buffers
      緩存與緩衝區的使用,例如寫入數據庫時,先緩衝至緩衝區而後批量寫入
    7. Pluggable Storage Englnes
      寫入時用到的存儲引擎,不一樣的引擎在硬件設備上保存數據的方式是不一樣的
    8. Files&Logs:
      日誌
    9. Management Services & Utilltles:
      輔助管理工具
  • 查詢的執行路徑
    在這裏插入圖片描述

    1. 客戶端軟件鏈接數據庫
    2. 鏈接數據庫使用通訊協議,基於mysql的IPA接口開發出來的通訊協議
    3. 創建通訊後驗證帳號等安全檢查,經過檢查後用戶發出請求,好比select,請求先到達mysql的查詢緩存,若是緩存中有,直接返回結果
    4. 若是緩存中沒有,將請求發送給解析器,生成解析樹,通過預處理生成新的解析樹
    5. 查詢優化器將新的解析樹中進行查詢優化
    6. 執行計劃,經過優化查詢,判斷出最佳查詢路徑,好比是否利用索引,利用那種索引等
    7. 將執行計劃提交給存儲引擎,經過存儲引擎鏈接數據庫進行訪問,訪問的數據是以塊的形式存放的,大小爲16k
  • 查詢緩存(只負責查詢的緩存)

    1. 查詢緩存(Query Cache )原理:
      緩存SELECT操做或預處理查詢的結果集和SQL語句,當有新的SELECT語句或預處理查詢語句請求,先去查詢緩存,判斷是否存在可用的記錄集
    2. 判斷標準
      與緩存的SQL語句,是否徹底同樣,區分大小寫(緩存中的數據,是根據查詢的SQL語句,進行哈希運算,放在緩存中,因此若是大小寫不一樣,哈希值就不一樣,在緩存中是查詢不到結果的)
    3. 優缺點
      1. 不須要對SQL語句作任何解析和執行,固然語法解析必須經過在先,直接從Query Cache中得到查詢結果,提升查詢性能
      2. 查詢緩存的判斷規則,不夠智能,也即提升了查詢緩存的使用門檻,下降其效率;
      3. 查詢緩存的使用,會增長檢查和清理Query Cache中記錄集的開銷
  • 哪些查詢可能不會被緩存

    1. 查詢語句中加了SQL_NO_CACHE參數,例如數據庫數據已經更新,緩存中的數據爲舊數據,能夠加此參數跳過查詢緩存
    2. 查詢語句中含有得到值的函數(常常變化的值),包含自定義函數,如:NOW()
      CURDATE()、GET_LOCK()、RAND()、CONVERT_TZ()等
    3. 對系統數據庫的查詢:mysql、information_schema查詢語句中使用SESSION級別變量或存儲過程當中的局部變量
    4. 查詢語句中使用了LOCK IN SHARE MODE、FOR UPDATE的語句,查詢語句中相似SELECT …INTO 導出數據的語句
    5. 對臨時表的查詢操做;存在警告信息的查詢語句;不涉及任何表或視圖的查詢語句;某用戶只有列級別權限的查詢語句
    6. 事務隔離級別爲Serializable時,全部查詢語句都不能緩存
  • 查詢緩存相關的服務器變量

       
       
       
       
       
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    與緩存相關的變量 MariaDB [(none)]> SHOW VARIABLES LIKE 'query_cache%'; +------------------------------+----------+ | Variable_name | Value | +------------------------------+----------+ | query_cache_limit | 1048576 | | query_cache_min_res_unit | 4096 | | query_cache_size | 33554432 | | query_cache_strip_comments | OFF | | query_cache_type | ON | | query_cache_wlock_invalidate | OFF | +------------------------------+----------+
    1. query_cache_min_res_unit
      查詢緩存中內存塊的最小分配單位,默認4k,較小值會減小浪費,但會致使更頻繁的內存分配操做,較大值會帶來浪費,會致使碎片過多,內存不足
    2. query_cache_limit
      單個查詢結果能緩存的最大值,默認爲1M,對於查詢結果過大而沒法緩存的語句,建議使用SQL_NO_CACHE
    3. query_cache_size
      查詢緩存總共可用的內存空間;單位字節,必須是1024的整數倍,最小值40KB,低於此值有警報,默認爲0
      以系統變量修改,僅支持以k爲單位
           
           
           
           
           
      • 1
      MariaDB [hellodb]> set global query_cache_size=33554432;
      在配置文件中修改支持以M爲單位
           
           
           
           
           
      • 1
      • 2
      • 3
      [root@hai7-8 ~]$vim /etc/my.cnf [mysqld] query_cache_size=30M
    4. query_cache_wlock_invalidate
      若是某表被其它的會話鎖定,是否仍然能夠從查詢緩存中返回結果,默認值爲OFF,表示能夠在表被其它會話鎖定的場景中繼續從緩存返回數據;ON則表示不容許。其餘事務在修改表時上鎖,若是這時候搜索,可能獲得的結果是髒數據。
    5. query_cache_type:
      是否開啓緩存功能,取值爲ON, OFF, DEMAND
      1. query_cache_type的值爲OFF或0時,查詢緩存功能關閉
      2. query_cache_type的值爲ON或1時,查詢緩存功能打開,SELECT的結果符合緩存條件即會緩存,不然,不予緩存,顯式指定SQL_NO_CACHE,不予緩存,此爲默認值
      3. query_cache_type的值爲DEMAND或2時,查詢緩存功能按需進行,顯式指定SQL_CACHE的SELECT語句纔會緩存;其它均不予緩存
  • SELECT語句的緩存控制

    1. SQL_CACHE: 顯式指定存儲查詢結果於緩存之中
    2. SQL_NO_CACHE: 顯式查詢結果不予緩存
  • 參看文獻
    https://mariadb.com/kb/en/library/server-system-variables/#query_cache_type
    https://dev.mysql.com/doc/refman/5.7/en/query-cache-configuration.html

  • 優化查詢緩存
    在這裏插入圖片描述

    1. 命中率是否能夠接受
      命中率就是屢次查詢,有幾回查詢是在緩存中查到的
      1. 若是能夠接受,那就不用優化
      2. 不能接受,進入第2大項判斷
    2. 判斷是否大部分查詢結果沒法緩存
      1. 大部分沒法緩存,判斷是否 query_cache_limit是否設置太小
        1. 不是此緣由則結束優化
        2. 單個緩存值設定過小,增大此值
      2. 大部分能夠緩存,進入第3項判斷
    3. 判斷是否發生了許多驗證工做(好比數據是否有效)
      1. 是,則去判斷緩存是否被碎片化(內存最小單位設置不合理,形成多碎片)
        1. 是,經過重設塊大小,或者清理碎片來優化
        2. 否,則判斷是否有不少由於內存太低而發生的修復工做
          1. 是,則調節緩存大小
          2. 否,則判斷是否有不少更新語句
            1. 是,結束優化,由於負載並不適合緩存
            2. 否,結束優化,有其餘東西配置錯誤
      2. 否,進入第4項判斷
    4. 判斷緩存是否啓用
      1. 是,多是該指令歷來沒有緩存過
      2. 否,啓動緩存功能
  • 查詢緩存的狀態變量,與存儲引擎無關,是系統的緩存變量

    1. 查詢緩存相關的狀態變量:
      SHOW GLOBAL STATUS LIKE ‘Qcache%’;
           
           
           
           
           
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      MariaDB [hellodb]> SHOW GLOBAL STATUS LIKE 'Qcache%'; +-------------------------+----------+ | Variable_name | Value | +-------------------------+----------+ | Qcache_free_blocks | 1 | | Qcache_free_memory | 33536824 | | Qcache_hits | 0 | | Qcache_inserts | 2 | | Qcache_lowmem_prunes | 0 | | Qcache_not_cached | 28 | | Qcache_queries_in_cache | 0 | | Qcache_total_blocks | 1 | +-------------------------+----------+
      1. Qcache_free_blocks:
        處於空閒狀態Query Cache中內存Block 數
      2. Qcache_total_blocks:
        Query Cache 中總Block ,當Qcache_free_blocks相對此值較大時,可能用內存碎片,執行FLUSH QUERY CACHE清理碎片
      3. Qcache_free_memory:
        處於空閒狀態的Query Cache 內存總量
      4. Qcache_hits:
        Query Cache 命中次數
      5. Qcache_inserts:
        向Query Cache 中插入新的Query Cache 的次數,即沒有命中的次數
      6. Qcache_lowmem_prunes:
        0記錄有多少條查詢由於內存不足而被移除出查詢緩存
      7. Qcache_not_cached:
        沒有被Cache 的SQL 數,包括沒法被Cache 的SQL 以及因爲query_cache_type設置的不會被Cache 的SQL語句
      8. Qcache_queries_in_cache:
        在Query Cache 中的SQL 數量
  • 命中率和內存使用率估算

    1. 查詢緩存中內存塊的最小分配單位query_cache_min_res_unit:
           
           
           
           
           
      • 1
      (query_cache_size - Qcache_free_memory) / Qcache_queries_in_cache
    2. 查詢緩存命中率
           
           
           
           
           
      • 1
      Qcache_hits/ ( Qcache_hits+ Qcache_inserts) * 100%
    3. 查詢緩存內存使用率
           
           
           
           
           
      • 1
      (query_cache_size–qcache_free_memory) / query_cache_size* 100%
  • InnoDB存儲引擎的緩衝池:
    一般InnoDB存儲引擎緩衝池的命中不該該小於99%

    1. 查看相關狀態變量
           
           
           
           
           
      • 1
      MariaDB [(none)]> SHOW GLOBAL STATUS LIKE 'innodb%read%'\G
    2. 經常使用狀態變量描述
      1. Innodb_buffer_pool_reads:
        表示從物理磁盤讀取頁的次數
      2. Innodb_buffer_pool_read_ahead:
        預讀的次數
      3. Innodb_buffer_pool_read_ahead_evicted:
        預讀頁,可是沒有讀取就從緩衝池中被替換的頁數量,通常用來判斷預讀的效率
      4. Innodb_buffer_pool_read_requests:
        從緩衝池中讀取頁次數
      5. Innodb_data_read:
        總共讀入的字節數
      6. Innodb_data_reads:
        發起讀取請求的次數,每次讀取可能須要讀取多個頁
    3. 相關計算
      在這裏插入圖片描述

7 提升數據庫性能-索引

7.1 索引概述

  • 索引做用方式
    將索引定義在查找時做爲查找條件的字段(如主鍵),將本來無序存放在磁盤存儲器上的數據,轉變爲樹狀結構,按索引定義排序,以達到快速獲得目標數據的功能;索引實如今存儲引擎,與數據庫和存儲引擎密切相關,存儲引擎不一樣,支持的索引頁大相徑庭
  • 優勢:
    1. 索引能夠下降服務須要掃描的數據量,減小了IO次數
    2. 索引能夠幫助服務器避免排序和使用臨時表
    3. 索引能夠幫助將隨機I/O轉爲順序I/O
  • 缺點:
    1. 佔用額外空間
    2. 影響插入速度,平衡樹結構要維持在一個正確狀態,增刪改數據都會改變平衡樹各節點中的索引數據內容,數據庫管理系統(DBMS)就會從新梳理樹的結構,確保正確

7.2 索引結構

  • B-TREE:與二叉樹相關

    1. 二叉樹
      在這裏插入圖片描述

      1. 二叉樹是遞歸定義的,每一個節點最多分兩個叉

        1. 最上邊的爲根節點
        2. 最下邊的爲葉子節點
        3. 中間的所有爲分支節點
      2. 查詢順序爲:例如查詢6號
        從根開始查,根爲5號比6小,因此從右邊開始查找,第二層爲8比6大,因此從左分支走到第三層 找到7比6大,再從左邊找獲得6。就上圖而言,找到6須要訪問4次I/O

  • B-TREE索引
    在這裏插入圖片描述

    1. 優化二叉樹,下降I/O次數,即訪問磁盤的次數,在每層放兩個數據,減小層數
    2. 在B-TREE中,每一個節點放2個數據,最多能夠有3各分支,
    3. 節點中的指針P1指向比此區間大的下一層節點,指針P2指向在此區間範圍的下一層節點,指針P3指向比此區間小的下一層節點
    4. 特徵
      1. 關鍵字分佈在整棵樹中
      2. 任何一個關鍵字出現且只出如今一個結點中
      3. 搜索有可能在非葉子結點結束
    5. 缺點:
      葉子節點之間沒有聯繫,若是要查範圍數據,好比10號到30號之間的數據,須要重複從根節點開始查詢
  • B+TREE
    在這裏插入圖片描述

    1. 特徵

      1. 只有葉子節點存放數據,其餘節點只放索引,分支節點不放數據,一樣的塊大小能夠存放更多的索引,減小整個樹的層次
      2. 在B+Tree的每一個葉子節點增長一個指向相鄰葉子節點的指針,提升了區間訪問性能
      3. 順序存儲,每個葉子節點到根結點的距離是相同的,查詢效率穩定
    2. 可使用B-Tree索引的查詢類型:

      1. 全值匹配:精確全部索引列
        如:姓wang,名xiaochun,年齡30
      2. 匹配最左前綴:即只使用索引的第一列
        如:姓wang
      3. 匹配列前綴:只匹配一列值開頭部分,
        如:姓以w開頭的
      4. 匹配範圍值:
        如:姓ma和姓wang之間
      5. 精確匹配某一列並範圍匹配另外一列
        如:姓wang,名以x開頭的
    3. B-Tree索引的限制

      1. 若是不從最左列開始,則沒法使用索引
        如:組合鍵爲name+city,查找city爲某地的用戶,是沒法使用索引的,由於city是針對name排序後,在name的基礎上再排序,單個city是沒有順序的
      2. 不能跳過索引中的列
        如:例如查看某人來自哪一個城市,直接查城市是不能匹配的
      3. 若是查詢中某個列是爲範圍查詢,那麼其右側的列都沒法再使用索引
        如:姓名以a開頭的全部人,若是加上右側city的索引,就會漏掉一部分a
  • Hash索引
    基於哈希表實現,只有精確匹配索引中的全部列的查詢纔有效,存儲引擎會根據全部的索引計算出一個哈希值,哈希索引將全部的哈希值存儲在索引中,索引自身只存儲索引列對應的哈希值和數據指針,索引結構緊湊,查詢性能好

    1. 適用場景:
      1. 只支持等值比較查詢,包括=, <=>, IN()
      2. Memory存儲引擎支持顯式hash索引,InnoDB和MyISAM存儲引擎不支持
    2. 不適合使用hash索引的場景:
      1. 不適用於順序查詢
        hash索引中存放哈希值和指針,而哈希值與原值不必定相同,所 以不能用來排序
      2. 不支持模糊匹配
      3. 不支持範圍查詢
      4. 不支持部分索引列匹配查找
        如A,B列索引,只查詢A列索引無效
  • 特別提示

    1. 索引列的順序和查詢語句的寫法應相匹配,才能更好的利用索引
    2. 爲優化性能,可能須要針對相同的列但順序不一樣建立不一樣的索引來知足不一樣類型的查詢需求

7.2 索引分類

  • 地理空間索引(Geospatial indexing ):
    MyISAM支持地理空間索引,可使用任意維度組合查詢,使用特有的函數訪問,經常使用於作地理數據存儲,使用很少
    InnoDB從MySQL5.7以後也開始支持

  • 全文索引(FULLTEXT):
    先定義一個詞庫,而後在文章中查找每一個詞條(term)出現的頻率和位置,把這樣的頻率和位置信息按照詞庫的順序概括,這樣就至關於對文件創建了一個以詞庫爲目錄的索引,這樣查找某個詞的時候就能很快的定位到該詞出現的位置
    InnoDB從MySQL 5.6以後也開始支持

  • 聚簇和非聚簇索引、二級(輔助)索引
    在這裏插入圖片描述

    1. 聚簇索引(Clustered Index),數據和索引在一個文件中,例如INNODB

      1. 特徵
        1. 表數據按照索引的的順序存儲,也就是說索引與表中的記錄物理順序一致,
        2. 對於彙集索引,葉子結點即存儲了真實的數據行,再也不有另外單獨的數據頁。
        3. 在一張表上最多隻能建立一個彙集索引,由於真實數據的物理順序只能有一種,系統默認會將主鍵設置爲聚簇索引
      2. 聚簇索引的二級索引:
        葉子節點不會保存引用的行的物理位置,而是保存了行的主鍵,經過二級索引查找行,存儲引擎須要找到二級索引的葉子節點得到對應的主鍵值,而後根據這個值去聚簇索引中查找到對應的行。
      3. 優勢
        1. 數據與葉子節點存儲在一塊兒,和主鍵一塊兒載入內存中,找到節點就能夠當即返回數據,只按主鍵搜索來講,獲取速度快
        2. 使用覆蓋索引掃描的查詢能夠直接使用節點中的主鍵值
      4. 缺點
        1. 插入速度嚴重依賴於插入順序,若是不是按照主鍵順序加載數據,那麼在加載完成後最好使用OPTIMIZE TABLE命令從新組織一下表
        2. 更新聚簇索引列的代價很高,由於會強制InnoDB將每一個被更新的行移動到新的位置
        3. 基於聚簇索引的表在插入新行,或者主鍵被更新致使須要移動行的時候,可能面臨「頁分裂」的問題
        4. 聚簇索引可能致使全表掃描變慢,尤爲是行比較稀疏,或者因爲頁分裂致使數據存儲不連續的時候
        5. 二級索引包含主鍵列,比較大,並且須要通過兩次B-TREE
    2. 非聚簇索引(Non- Clustered Index),索引和數據獨立存放
      例如mysql數據庫使用的MyISAM存儲引擎,生成3個文件,分別存放索引、表結構、數據

      1. 特徵
        1. 表數據存儲順序與索引順序無關。
        2. 對於非彙集索引,葉結點包含索引字段值及指向數據頁數據行的邏輯指針,其行數量與數據錶行數據量一致
        3. 非聚簇索引能夠有多個
      2. 非聚簇索引的二級索引:
        主鍵索引和二級索引區別不大,只是主鍵索引是惟一的存放的是主鍵,二級索引存放的是輔助鍵
  • 稠密索引、稀疏索引
    是否索引了每個數據項

    1. 稠密索引
      每一個記錄都有一個索引項,記錄在數據區存放是任意的,但索引是按序的
    2. 稀疏數據線
      將全部數據記錄關鍵字值分紅許多組,每組一個索引項
  • 簡單索引、組合索引

    1. 單一索引
      索引列爲一列的狀況,即新建索引的語句只實施在一列上

    2. 複合索引,
      由多列建立的索引稱爲複合索引,在符合索引中的前導列必須出如今where條件中,索引纔會被使用

  • 主鍵索引與惟一鍵索引

    1. 惟一索引
      惟一索引比較好理解,不容許具備索引值相同的行,這樣的索引選擇性是最好的

    2. 主鍵索引
      主鍵索引就是惟一索引,不過主鍵索引是在建立表時就建立了,惟一索引能夠隨時建立。

    3. 區別

      1. 主鍵是主鍵約束+惟一索引
      2. 主鍵必定包含一個惟一索引,但惟一索引不是主鍵
      3. 惟一索引列容許空值,但主鍵列不容許空值
      4. 一個表只能有一個主鍵,但能夠有多個惟一索引
  • 覆蓋索引
    select的數據列只用從索引中就可以取得,沒必要讀取數據行,換句話說查詢列要被所建的索引覆蓋

  • 冗餘和重複索引:

    1. 冗餘索引:(A),(A,B)
      複合索引A,B已經對A進行排序,再創建A索引沒有意義
    2. 重複索引:已經有索引,再次創建索引
      針對相同的字段重複創建,例如字段age,先創建idx_age1,又在其上創建idx_age2

7.4 索引優化策略:

  1. 獨立地使用列
    儘可能避免其參與運算,獨立的列指索引列不能是表達式的一部分,也不能是函數的參數,在where條件中,始終將索引列單獨放在比較符號的一側
       
       
       
       
       
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    '創建索引在字段age上' MariaDB [hellodb]> create index index_age ON students(age); 'age+5就是指索引參與運算,混在一塊兒計算是沒法利用索引的' MariaDB [hellodb]> select * from students where age+5=25; +-------+--------------+-----+--------+---------+-----------+ | StuID | Name | Age | Gender | ClassID | TeacherID | +-------+--------------+-----+--------+---------+-----------+ | 9 | Ren Yingying | 20 | F | 6 | NULL | | 22 | Xiao Qiao | 20 | F | 1 | NULL | +-------+--------------+-----+--------+---------+-----------+ '若是必定要運算,應該講運算放在=右邊' MariaDB [hellodb]> select * from students where age=20+5;
    1. 左前綴索引
      構建索引時指定字段字符數,具體長度要經過索引選擇性來評估
      例如:將名字做爲索引時,表內名字都在10個字符以上,通過評估僅使用前3個字符就能夠達到區別各行的目的,就能夠考慮左前綴索引,限定爲3各字符
    2. 多列索引
      AND操做時更適合使用多列索引,而非爲每一個列建立單獨的索引
    3. 選擇合適的索引列順序
      無排序和分組時,將選擇性最高放左側
    4. 只要列中含有NULL值,就最好不要在此例設置索引,複合索引若是有NULL值,此列在使用時也不會使用索引
    5. 儘可能使用短索引,若是能夠,應該制定一個前綴長度
    6. 對於常常在where子句使用的列,最好設置索引
    7. 對於有多個列where或者order by子句,應該創建複合索引
    8. 對於like語句,以%或者‘-’開頭的不會使用索引,以%結尾會使用索引
    9. 儘可能不要使用not in和<>操做
  • SQL語句性能優化
    1. 查詢時,能不要*就不用*,儘可能寫全字段名
    2. 大部分狀況鏈接效率遠大於子查詢
    3. 多表鏈接時,儘可能小表驅動大表,即小表join 大表
    4. 在有大量記錄的表分頁時使用limit
    5. 對於常用的查詢,能夠開啓緩存
    6. 多使用explain和profile分析查詢語句
    7. 查看慢查詢日誌,找出執行時間長的sql語句優化
</div>
					<link href="https://csdnimg.cn/release/phoenix/mdeditor/markdown_views-7f770a53f2.css" rel="stylesheet">
            </div>
相關文章
相關標籤/搜索