mysql 詳解

一、簡介

MySQL的歷史能夠追溯到1979年,一個名爲Monty Widenius的程序員在爲TcX的小公司打工,而且用BASIC設計了一個報表工具,使其能夠在4MHz主頻和16KB內存的計算機上運行。當時,這只是一個很底層的且僅面向報表的存儲引擎,名叫Unireg。【MySQL早期叫Unireg】早期輕量級,後來發展到巨無霸(淘寶、faceboock)MySQL AB是由MySQL創始人和主要開發人創辦的公司。MySQL AB最初是由David Axmark、Allan Larsson和Michael「Monty」Widenius在瑞典創辦的。
mysql 詳解
SQL標準:ANSI SQL
SQL-86, SQL-89, SQL-92, SQL-99, SQL-03html

  • SQL四種語言:DDL,DML,DCL,TCL
    DDL(Data Definition Language)數據定義語言
    DML(Data Manipulation Language)數據操縱語言
    DCL(Data Control Language)數據庫控制語言 受權,角色控制等
    TCL(Transaction Control Language)事務控制語言
    SAVEPOINT 設置保存點
    ROLLBACK 回滾
    SET TRANSACTION

SQL主要分紅四部分:
(1)數據定義。(SQL DDL)用於定義SQL模式、基本表、視圖和索引的建立和撤消操做。
(2)數據操縱。(SQL DML)數據操縱分紅數據查詢和數據更新兩類。數據更新又分紅插入、刪除、和修改三種操做。
(3)數據控制。包括對基本表和視圖的受權,完整性規則的描述,事務控制等內容。
(4)嵌入式SQL的使用規定。涉及到SQL語句嵌入在宿主語言程序中使用的規則。前端

mysql 詳解

啓動3306端口 (鏈接池認證成功進入,不成功退出;(Check Memory -Caches)查詢緩存,直接查找該sql語句的執行結果,若是命中直接返回,不然繼續生成查詢計劃、解析sql語句;經優化,查找buffers cache裏面的語句,嘗試加載buffers cache語句,若是buffers cache裏沒有語句,則經過特定引擎與io設備進行交互。)mysql

查詢的執行路徑:
mysql 詳解git

平常的學習和工做中我確認深深感覺到數據結構和算法的重要性,不少東西,若是你願意稍稍往深處挖一點,那麼撲面而來的必定是各類數據結構和算法知識。
經典的BTREE索引數據結構以下圖:
mysql 詳解程序員

B-Tree 索引是 MySQL 數據庫中使用最爲頻繁的索引類型,除了 Archive 存儲引擎以外的其餘全部的存儲引擎都支持 B-Tree 索引。不只僅在 MySQL 中是如此,實際上在其餘的不少數據庫管理系統中B-Tree 索引也一樣是做爲最主要的索引類型,這主要是由於B-Tree 索引的存儲結構在數據庫的數據檢索中有很是優異的表現。正則表達式

通常來講, MySQL 中的 B-Tree 索引的物理文件大多都是以 Balance Tree 的結構來存儲的,也就是全部實際須要的數據都存放於 Tree 的 Leaf Node ,並且到任何一個 Leaf Node 的最短路徑的長度都是徹底相同的,因此咱們你們都稱之爲 B-Tree 索引固然,可能各類數據庫(或 MySQL 的各類存儲引擎)在存放本身的 B-Tree 索引的時候會對存儲結構稍做改造。如 Innodb 存儲引擎的 B-Tree 索引實際使用的存儲結構其實是 B+Tree ,也就是在 B-Tree 數據結構的基礎上作了很小的改造,在每個Leaf Node 上面出了存放索引鍵的相關信息以外,還存儲了指向與該 Leaf Node 相鄰的後一個 LeafNode 的指針信息,這主要是爲了加快檢索多個相鄰 Leaf Node 的效率考慮。redis

B+樹是一個平衡的多叉樹,從根節點到每一個葉子節點的高度差值不超過1,並且同層級的節點間有指針相互連接。算法

在B+樹上的常規檢索,從根節點到葉子節點的搜索效率基本至關,不會出現大幅波動,並且基於索引的順序掃描時,也能夠利用雙向指針快速左右移動,效率很是高。
mysql 詳解sql

所以,B+樹索引被普遍應用於數據庫、文件系統等場景。順便說一下,xfs文件系統比ext3/ext4效率高不少的緣由之一就是,它的文件及目錄索引結構所有采用B+樹索引,而ext3/ext4的文件目錄結構則採用Linked list, hashed B-tree、Extents/Bitmap等索引數據結構,所以在高I/O壓力下,其IOPS能力不如xfs。mongodb

Lex & Yacc 是用來生成詞法分析器和語法分析器的工具,它們的出現簡化了編譯器的編寫。Lex & Yacc 分別是由貝爾實驗室的 Mike Lesk 和 Stephen C. Johnson 在 1975 年發佈。
mysql 詳解

MySQL事務:

事務:一組原子性的SQL查詢,或者說一個獨立工做單元。

    事務日誌:

ACID測試:
    A:atomicity,原子性;整個事務中的全部操做要麼所有成功執行,要麼所有失敗後回滾;
    C:consistency, 一致性;數據庫老是從一個一致性狀態轉換爲另外一個一致性狀態;
    I:Isolation,隔離性;一個事務所作出的操做在提交以前,是不能爲其它所見;隔離有多種隔離級別;
    D:durability: 持久性;一旦事務提交,其所作的修改會永久保存於數據庫中;

事務:
    啓動事務:START TRANSACTION
    結束事務:
        (1) COMMIT:提交
        (2) ROLLBACK: 回滾

    注意:只有事務型存儲引擎方能支持此類操做;

    建議:顯式請求和提交事務,而不要使用「自動提交」功能;
        autocommit={1|0}

    事務支持savepoint
        SAVEPOINT identifier
        ROLLBACK [WORK] TO [SAVEPOINT] identifier
        RELEASE SAVEPOINT identifier

    事務隔離級別:
        READ UNCOMMITTED (讀未提交)【髒讀、不可重複讀、幻讀】
        READ COMMITTED (讀提交)【不可重複讀、幻讀】
        REPEATABLE READ (可重讀)【幻讀】【默認[InnoDB]MySQL存儲引擎使用的隔離級別"可重讀"】
        SERIALIZABLE (可串行化)【加鎖讀】

        可能存在問題:
            髒讀;
            不可重複讀;
            幻讀;
            加鎖讀;

MySQL用戶和權限管理:

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

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

    程序類:
        FUNCTION
        PROCEDURE
        TRIGGER

        CREATE, ALTER, DROP, EXCUTE

    庫和表級別:TABLE or DATABASE
        ALTER
        CREATE 
        CREATE VIEW
        DROP
        INDEX
        SHOW VIEW
        GRANT OPTION:可以把本身得到的權限贈經其餘用戶一個副本;

    數據操做:
        SELECT
        INSERT
        DELETE
        UPDATE

    字段級別:
        SELECT(col1,col2,...)
        UPDATE(col1,col2,...)
        INSERT(col1,col2,...)

    全部有限:ALL PRIVILEGES, ALL

    元數據數據庫:mysql
        受權表:
            db, host, user
            columns_priv, tables_priv, procs_priv, proxies_priv

用戶帳號:
    'USERNAME'@'HOST':
        @'HOST':
            主機名;
            IP地址或Network; 
            通配符:
                %, _: 172.16.%.%

    建立用戶:CREATE USER
        CREATE USER 'USERNAME'@'HOST' [IDENTIFIED BY 'password'];

        查看用戶得到的受權:SHOW GRANTS FOR
            SHOW GRANTS FOR 'USERNAME'@'HOST'

    用戶重命名:RENAME USER
        RENAME USER old_user_name TO new_user_name

    刪除用戶:DROP USER 'USERNAME'@'HOST'

    修改密碼:
        (1) SET PASSWORD FOR
        (2) UPDATE mysql.user SET password=PASSWORD('your_password') WHERE clause;
        (3) mysqladmin password
             mysqladmin [OPTIONS] command command....
                -u, -h, -p

    忘記管理員密碼的解決辦法:
        (1) 啓動mysqld進程時,爲其使用:--skip-grant-tables --skip-networking
        (2) 使用UPDATE命令修改管理員密碼
        (3) 關閉mysqld進程,移除上述兩個選項,重啓mysqld; 

受權:GRANT
    GRANT priv_type[,...] ON [{table|function|procedure}] db.{table|routine} TO 'USERNAME'@'HOST' [IDENTIFIED BY 'password']
        [REQUIRE SSL] [WITH with_option]

        with_option:
            GRANT OPTION
          | MAX_QUERIES_PER_HOUR count
          | MAX_UPDATES_PER_HOUR count
          | MAX_CONNECTIONS_PER_HOUR count
          | MAX_USER_CONNECTIONS count

取消受權:REVOKE
    REVOKE priv_type [(column_list)] [, priv_type [(column_list)]] ... ON [object_type] priv_level FROM user [, user] ...

二、各存儲引擎的特性

InnoDB:
            事務:事務日誌
            外鍵:
            MVCC:
            聚簇索引:
                聚簇索引以外的其它索引,一般稱爲輔助索引
            行級鎖:間隙鎖
            支持輔助索引
            支持自適應hash索引
            支持熱備份

        MyISAM:
            全文索引
            壓縮:用於實現數據倉庫,能節約存儲空間並提高性能
            空間索引
            表級鎖
            延遲更新索引

            不支持事務、外鍵和行級鎖
            崩潰後沒法安全恢復數據

            適用場景:只讀數據、較小的表、可以容忍崩潰後的修改操做和數據丟失

        ARCHIVE:
            僅支持INSERT和SELECT,支持很好壓縮功能;
            適用於存儲日誌信息,或其它按時間序列實現的數據採集類的應用;

            不支持事務,不能很好的支持索引;

        CSV:
            將數據存儲爲CSV格式;不支持索引;僅適用於數據交換場景;

        BLACKHOLE:
            沒有存儲機制,任何發往此引擎的數據都會丟棄;其會記錄二進制日誌,所以,經常使用於多級複製架構中做中轉服務器;

        MEMORY:
            保存數據在內存中,內存表;經常使用於保存中間數據,如週期性的聚合數據等;也用於實現臨時表
            支持hash索引,使用表級鎖,不支持BLOB和TEXT數據類型

        MRG_MYISAM:是MYISAM的一個變種,可以將多個MyISAM表合併成一個虛表;

        NDB:是MySQL CLUSTER中專用的存儲引擎

    第三方的存儲引擎:

        OLTP類:
            XtraDB: 加強的InnoDB,由Percona提供;
                編譯安裝時,下載XtraDB的源碼替換MySQL存儲引擎中的InnoDB的源碼

            PBXT: MariaDB自帶此存儲引擎
                支持引擎級別的複製、外鍵約束,對SSD磁盤提供適當支持;
                支持事務、MVCC

            TokuDB: 使用Fractal Trees索引,適用存儲大數據,擁有很好的壓縮比;已經被引入MariaDB;

        列式存儲引擎:
            Infobright: 目前較有名的列式引擎,適用於海量數據存儲場景,如PB級別,專爲數據分析和數據倉庫設計;
            InfiniDB
            MonetDB
            LucidDB

        開源社區存儲引擎:
            Aria:前身爲Maria,可理解爲加強版的MyISAM(支持崩潰後安全恢復,支持數據緩存)
            Groona:全文索引引擎,Mroonga是基於Groona的二次開發版
            OQGraph: 由Open Query研發,支持圖結構的存儲引擎
            SphinxSE: 爲Sphinx全文搜索服務器提供了SQL接口
            Spider: 能數據切分紅不一樣分片,比較高效透明地實現了分片(shared),並支持在分片上支持並行查詢;

三、MySQL 數據類型

MySQL中定義數據字段的類型對你數據庫的優化是很是重要的。MySQL支持多種類型,大體能夠分爲字符型、數值型、日期時間型、內建類型。一般也可分爲三類:數值、日期/時間和字符串(字符)類型。

字符型:
        CHAR, BINARY:定長數據類型;【CHAR不區分字符大小寫,BINARY區分字符大小寫】
        VARCHAR, VARBINARY:變長數據類型;須要結束符;
        TEXT:TINYTEXT, TEXT, MEDIUMTEXT, LONGTEXT
        BLOB: TINYBLOB, BLOB, MEDIUMBLOB, LONGBLOB
        ENUM, SET

ENUM 類型由於只容許在集合中取得一個值,有點相似於單選項。SET 類型與 ENUM 類型類似但不相同。SET 類型能夠從預約義的集合中取得任意數量的值。
mysql 詳解

數值型:
        精確數值型:
            整型:TINYINT, SMALLINT, MEDIUMINT, INT, BIGINT
            十進制型:DECIMAL   【在金融領域中一般用的是十近制】
        近似數值型
            浮點型:
                FLOAT
                DOUBLE
          BIT 【通常不建議使用】

mysql 詳解

日期時間型:
        DATE
        TIME
        DATETIME
        TIMESTAMP
        YEAR(2), YEAR(4)

mysql 詳解

字符類型修飾符:
        NOT NULL: 非空約束;
        NULL:
        DEFAULT 'STRING': 指明默認值;
        CHARACTER SET '':使用的字符集;
        COLLATION:使用的排序規則

    整型數據修飾型:
        NOT NULL
        NULL
        DEFAULT NUMBER

        AUTO_INCREMENT:
            UNSIGNED
            PRIMARY KEY|UNIQUE KEY
            NOT NULL

            mysql> SELECT LAST_INSERT_ID();

    日期時間型修飾符:
        NOT NULL
        NULL
        DEFAULT 

    內建類型SET和ENUM的修飾符:
        NOT NULL
        NULL
        DEFAULT

四、SQL MODE

經常使用SQL MODE有:TRADITIONAL, STRICT_TRANS_TABLES, or STRICT_ALL_TABLES。SQL_MODE多是比較容易讓開發人員和DBA忽略的一個變量,默認爲空。SQL_MODE的設置是比較有風險的一種設置,由於在這種設置下能夠容許一些非法操做,好比能夠將NULL插入NOT NULL的字段中,也能夠插入一些非法日期,如「2019-12-33」。所以在生產環境中強烈建議開發人員將這個值設爲嚴格模式,這樣有些問題能夠在數據庫的設計和開發階段就能發現,而若是在生產環境下運行數據庫後發現這類問題,那麼修改的代價將變得十分巨大。

mysql 詳解
mysql 詳解

sql_mode經常使用值以下: 
ONLY_FULL_GROUP_BY:
對於GROUP BY聚合操做,若是在SELECT中的列,沒有在GROUP BY中出現,那麼這個SQL是不合法的,由於列不在GROUP BY從句中

NO_AUTO_VALUE_ON_ZERO:
該值影響自增加列的插入。默認設置下,插入0或NULL表明生成下一個自增加值。若是用戶 但願插入的值爲0,而該列又是自增加的,那麼這個選項就有用了。

STRICT_TRANS_TABLES:
在該模式下,若是一個值不能插入到一個事務表中,則中斷當前的操做,對非事務表不作限制

NO_ZERO_IN_DATE:
在嚴格模式下,不容許日期和月份爲零

NO_ZERO_DATE:
設置該值,mysql數據庫不容許插入零日期,插入零日期會拋出錯誤而不是警告。

ERROR_FOR_DIVISION_BY_ZERO:
在INSERT或UPDATE過程當中,若是數據被零除,則產生錯誤而非警告。如 果未給出該模式,那麼數據被零除時MySQL返回NULL

NO_AUTO_CREATE_USER:
禁止GRANT建立密碼爲空的用戶

NO_ENGINE_SUBSTITUTION:
若是須要的存儲引擎被禁用或未編譯,那麼拋出錯誤。不設置此值時,用默認的存儲引擎替代,並拋出一個異常

PIPES_AS_CONCAT:
將"||"視爲字符串的鏈接操做符而非或運算符,這和Oracle數據庫是同樣的,也和字符串的拼接函數Concat相相似

ANSI_QUOTES:
啓用ANSI_QUOTES後,不能用雙引號來引用字符串,由於它被解釋爲識別符

ORACLE的sql_mode設置等同:PIPES_AS_CONCAT, ANSI_QUOTES, IGNORE_SPACE, NO_KEY_OPTIONS, NO_TABLE_OPTIONS, NO_FIELD_OPTIONS, NO_AUTO_CREATE_USER.

五、SQL語法

建立一個數據庫

使用 create database 語句可完成對數據庫的建立, 建立命令的格式以下:
create database 數據庫名 [其餘選項];

建立數據庫表

使用 create table 語句可完成對錶的建立, create table 的常見形式:
create table 表名稱(列聲明);

表中插入數據

insert 語句能夠用來將一行或多行數據插到數據庫表中, 使用的通常形式以下:
insert [into] 表名 [(列名1, 列名2, 列名3, ...)] values (值1, 值2, 值3, ...);

查詢表中的數據

select 語句經常使用來根據必定的查詢規則到數據庫中獲取數據, 其基本的用法爲:
select 列名稱 from 表名稱 [查詢條件];

按特定條件查詢:
where 關鍵詞用於指定查詢條件, 用法形式爲: select 列名稱 from 表名稱 where 條件;

更新表中的數據

update 語句可用來修改表中的數據, 基本的使用形式爲:
update 表名稱 set 列名稱=新值 where 更新條件;

刪除表中的數據

delete 語句用於刪除表中的數據, 基本用法爲:
delete from 表名稱 where 刪除條件;

建立後表的修改

添加列
基本形式: alter table 表名 add 列名 列數據類型 [after 插入位置];
修改列
基本形式: alter table 表名 change 列名稱 列新名稱 新數據類型;
刪除列
基本形式: alter table 表名 drop 列名稱;
重命名錶
基本形式: alter table 表名 rename 新表名;
刪除整張表
基本形式: drop table 表名;
刪除整個數據庫
基本形式: drop database 數據庫名;

SELECT語句的執行流程:
FROM Clause --> WHERE Clause --> GROUP BY --> HAVING Clause --> ORDER BY --> SELECT --> LIMIT
mysql 詳解

  • 單表查詢:
    SELECT

    [ALL | DISTINCT | DISTINCTROW ]
                  [SQL_CACHE | SQL_NO_CACHE] 
                select_expr [, select_expr ...]
                [FROM table_references
                [WHERE where_condition]
                [GROUP BY {col_name | expr | position}
                  [ASC | DESC], ... [WITH ROLLUP]]
                [HAVING where_condition]
                [ORDER BY {col_name | expr | position}
                  [ASC | DESC], ...]
                [LIMIT {[offset,] row_count | row_count OFFSET offset}]
                [FOR UPDATE | LOCK IN SHARE MODE]
    
                DISTINCT: 數據去重;
                SQL_CACHE: 顯式指定存儲查詢結果於緩存之中;
                SQL_NO_CACHE: 顯式查詢結果不予緩存;
    
                query_cache_type的值爲'ON'時,查詢緩存功能打開;
                    SELECT的結果符合緩存條件即會緩存,不然,不予緩存;
                    顯式指定SQL_NO_CACHE,不予緩存;
                query_cache_type的值爲'DEMAND'時,查詢緩存功能按需進行;
                    顯式指定SQL_CACHE的SELECT語句纔會緩存;其它均不予緩存;
    
            字段顯示可使用別名:
                col1 AS alias1, col2 AS alias2, ...
    
            WHERE子句:指明過濾條件以實現「選擇」的功能:
                過濾條件:布爾型表達式;
    
                算術操做符:+, -, *, /, %
                比較操做符:=, !=, <>, <=>, >, >=, <, <=
    
                    BETWEEN min_num AND max_num
                    IN (element1, element2, ...)
                    IS NULL
                    IS NOT NULL
                    LIKE: 
                        %: 任意長度的任意字符;
                        _:任意單個字符;
                    RLIKE:
                    REGEXP:匹配字符串可用正則表達式書寫模式;
    
                邏輯操做符:
                    NOT
                    AND
                    OR
                    XOR
    
            GROUP:根據指定的條件把查詢結果進行「分組」以用於作「聚合」運算:
                avg(), max(), min(), count(), sum()
    
            HAVING: 對分組聚合運算後的結果指定過濾條件;
    
            ORDER BY: 根據指定的字段對查詢結果進行排序;
                升序:ASC
                降序:DESC
    
            LIMIT [[offset,]row_count]:對查詢的結果進行輸出行數數量限制;
    
            對查詢結果中的數據請求施加「鎖」:
                FOR UPDATE: 寫鎖,排他鎖;
                LOCK IN SHARE MODE: 讀鎖,共享鎖
  • 多表查詢:
    交叉鏈接:笛卡爾乘積;
    內鏈接:
    等值鏈接:讓表之間的字段以「等值」創建鏈接關係;
    不等值鏈接
    天然鏈接
    自鏈接
    外鏈接:
    左外鏈接:
    FROM tb1 LEFT JOIN tb2 ON tb1.col=tb2.col
    右外鏈接
    FROM tb1 RIGHT JOIN tb2 ON tb1.col=tb2.col

  • 子查詢:在查詢語句嵌套着查詢語句
    基於某語句的查詢結果再次進行的查詢

    用在WHERE子句中的子查詢:
                (1) 用於比較表達式中的子查詢;子查詢僅能返回單個值;
                    SELECT Name,Age FROM students WHERE Age>(SELECT avg(Age) FROM students);
                (2) 用於IN中的子查詢:子查詢應該單鍵查詢並返回一個或多個值從構成列表;
                    SELECT Name,Age FROM students WHERE Age IN (SELECT Age FROM teachers);
                (3) 用於EXISTS;
    
            用於FROM子句中的子查詢;
                使用格式:SELECT tb_alias.col1,... FROM (SELECT clause) AS tb_alias WHERE Clause; 
                示例:
                SELECT s.aage,s.ClassID FROM (SELECT avg(Age) AS aage,ClassID FROM students WHERE ClassID IS NOT NULL GROUP BY ClassID) AS s WHERE s.aage>30;
  • 聯合查詢:UNION
    SELECT Name,Age FROM students UNION SELECT Name,Age FROM teachers;

    六、MySQ設計規範

    數據庫設計儘可能遵循第三範式(3NF)的要求。即某個表只包括其自己基本的屬性,當不是它們自己所具備的屬性時需進行分解。表之間的關係經過外鍵相鏈接。它具備如下特色:有一組表專門存放經過鍵鏈接起來的關聯數據。
    對於因效率等緣由,沒法遵循第三範式的,應該在設計文檔中明示緣由,並說明如何保持數據的一致性。

1   命名規範
(1) 數據庫名、表名、字段名必須使用小寫字母,並採用下劃線」_」分割。
(2) 數據庫名、表名、字段名禁止超過32個字符,須見名知意,建議使用名詞不是動詞。
(3) 數據庫名、表名、字段名禁止使用MySQL保留字。
(4) 臨時庫名、表名必須以tmp爲前綴,並以日期爲後綴。
(5) 備份庫名、表名必須以bak爲前綴,並以日期爲後綴。
2   基礎規範
(1) 使用INNODB存儲引擎
(2) 表字符集使用UTF8
(3) 全部表都須要添加註釋
(4) 單表數據量建議控制在5000W之內
(5) 數據庫表建議不存儲圖、文件等大數據
(6) 禁止在線上作數據庫壓力測試操做
(7) 全部字段須定義爲not null,根據業務可指定default值
3   庫表設計
(1) 庫名格式爲 組織機構_xxx[_xxx],好比以toon基礎爲例,其中「toon_」爲前綴,xxx爲實際數據庫名稱,使用各模塊的項目名稱字段設計。
(2) 表名中含有單詞所有采用單數形式,多個單詞之間使用」_」分割
(3) 同業務模塊表,建議在表名前增長模塊縮寫。
示例:客戶表:cust_customer
客戶聯繫方式:cust_contact
(4) 分表命名規則:原代表_數字,示例:cust_customer _01
(5) 全部表添加註釋。
(6) 全部表必需要顯式指定主鍵。
(7) 單表控制字段數量,30個字段的上限。
(8) 單表數據量建議控制在2000W~5000W之內
簡單字段類型建議 5000W之內,好比int,tinyint,bigint等
複雜字段類型建議 2000W 之內,好比varchar(n>2048),text等
(9) 關聯表命名規則:表a_表b,若是存在模塊縮寫,根據實際的業務須要保留一個模塊縮寫
示例:
房客關係表: prt_property_customer
4   字段設計
類型  字節  有/無符號   最小值 最大值
TINYINT 1   有   -128    127
        無   0   255
SMALLINT    2   有   -32768  32767
        無   0   65535
MEDIUMINT   3   有   -8388608    8388607
        無   0   16777215
INT 4   有   -2147483648 2147483647
        無   0   4294967295
BIGINT  8   有   -9223372036854775808    9223372036854775807
        無   0   18446744073709551615
(1) 越小越好的原則,選擇合適的數據類型,數據類型所佔用字節數越小越好;數值類型取值參考下表:

如主鍵取值上限不超過42億,建議不用BIGINT
(2) 越簡單越好的原則,字段能用數值型的不要用字符型。
(3) 儘可能避免使用 text/blob數據類型, 若確實須要,根據訪問, 更新頻次, 看是否有必要從 主表拆分出來。
(4) 使用TINYINT代替ENUM、SET。
(5) 字符串類型,比較小而且固定好比MD5值等選擇CHAR,不然選擇VARCHAR。
使用盡量小的VARCHAR字段,VARCHAR(N)中的N表示的是字符數而非字節數,一個漢字佔用三個字節,一個字母佔用一個字節。
(6) 字段須指定NOT NULL。
(7) 經常使用字段類型推薦
id主鍵:bigint或int,視數據增加範圍選擇,自增;
phone:varchar(15);
email:varchar(254);
郵編:varchar(11);
枚舉型數據:tinyint;
url:varchar(2083);
img:varchar(2083);
IP:varchar(45)或轉整型存儲;
Money:DECIMAL(19,4);
Longitude:DECIMAL(9,6);
Latitude:DECIMAL(8,6)。  

5   索引設計
(1) 非惟一索引必須按照「idx_字段名稱_字段名稱[_字段名]」進行命名。
(2) 惟一索引必須按照「uniq_字段名稱_字段名稱[_字段名]」進行命名。
(3) 控制索引數量,單表索引數量不超過5個,單個索引字段不超過5個。
(4) 索引儘可能健在區分度性高的列上,不在低區分度列上創建索引,例如性別。
(5) 不要在頻繁更新的列上建索引,不在索引列進行數學運算和函數運算。
(6) 合理建立聯合索引(避免冗餘),(a,b,c) 至關於 (a) 、(a,b) 、(a,b,c)
(7) 重要的SQL必須被索引,UPDATE、DELETE語句的WHERE條件列,ORDER BY、GROUP BY、DISTINCT的字段,多表JOIN的字段
(8) 不使用%前綴的查詢,如like 「%ab」;不使用負向查詢,如not in/like(推薦考慮用全文檢索sphinx)。

6   SQL設計
(1) sql語句儘量簡單,大的sql根據業務拆分紅小的sql語句(充分利用QUERY CACHE和充分利用多核CPU)。
(2) limit分頁注意效率。limit越大,效率越低。能夠改寫limit,好比例子改寫:select id from t limit 10000, 10;  =>  select id from t where id > 10000 limit10。
(3) 減小與數據庫的交互次數,儘可能使用批量sql語句。
(4) 注意使用性能分析的工具
Sql explain  /  showprofile   /    mysqlsla
(5) 建議SQL關鍵字所有是大寫,每一個詞只容許有一個空格
(6) SQL語句不能夠出現類型隱式轉換,好比 select id from 表 where id='1'
(7) IN條件裏面的數據數量要少,使用exist代替in,exist在一些場景查詢會比in快
在兩個均可以使用的狀況下,建議經過執行計劃來作取捨。
(8) 禁止在數據庫中跑大查詢
(9) 能不用NOT IN就不用NOT IN。
(10)    在SQL語句中,不建議使用模糊前綴匹配操做,好比like
(11)    關於分頁查詢:程序裏建議合理使用分頁來提升效率limit,offset較大要配合子查詢使用
(12)    使用預編譯語句,只傳參數,比傳遞SQL語句更高效;一次解析,屢次使用;下降SQL注入機率

7   行爲規範
(1) 數據庫設計須有DBA參與,表結構變動必須通知DBA;
(2) 批量導入、導出或者批量更新數據,必須DBA進行審覈,執行;
(3) 建議對同一個表的屢次alter操做合併爲一次操做;
(4) 不要在MySQL數據庫中存放業務邏輯;
(5) 建議禁止存儲過程、函數、觸發器的使用。

七、經常使用命令

一、刪除全部匿名用戶
        mysql> DROP USER ''@'localhost';
        mysql> DROP USER ''@'www.xxx.com';

        用戶賬號由兩部分組成:username@host
            host還可使用通配符:
                %: 任意長度的任意字符
                _: 匹配任意單個字符

    二、給全部的root用戶設定密碼:
        第一種方式:
            mysql> SET PASSWORD FOR username@host = PASSWORD('your_passwrod');

        第二種方式:
            mysql> UPDATE user SET password = PASSWORD('your_password') WHERE user = 'root';
            mysql> FLUSH PRIVILEGES;

        第三種方式:
            # mysqladmin -uUserName -hHost password 'new_password' -p
            # mysqladmin -uUserName -hHost -p flush-privileges

建立新用戶# 建立用戶和設置密碼
CREATE USER '新用戶'@'localhost' IDENTIFIED BY '新密碼';
對用戶受權
GRANT ALL PRIVILEGES ON . TO '新用戶'@‘localhost' WITH GRANT OPTION;

連入MySQL服務器
    mysql client <--mysql protocol--> mysqld

        mysqld接收鏈接請求:
            本地通訊:客戶端與服務器端位於同一主機,並且還要基於127.0.0.1(localhost)地址或lo接口進行通訊;
                Linux OR Unix: Unix Sock, /tmp/mysql.sock, /var/lib/mysql/mysql.sock
                Windows: memory, pipe
            遠程通訊:客戶端與服務器位於不一樣的主機,或在同一主機便使用非迴環地址通訊
                TCP socket

        客戶端工具:mysql, mysqladmin, mysqldump, mysqlcheck
            [client]

            通行的選項:
                -u, --user=
                -h, --host=
                -p, --password=
                --protocol={tcp|socket|memory|pipe}
                --port=
                --socket=    例如:/tmp/mysql.sock

【注意格式-u和-p後沒有空格是連在一塊兒的,若是密碼想要不顯示能夠這樣:mysql -uroot -p 回車輸入密碼】

            mysql監聽的端口: 3306/tcp

        非客戶端類的管理工具:myisamchk, myisampack

    mysql工做模式: 
        交互式模式
            mysql> 
        腳本模式
            mysql < /path/to/mysql_script.sql

    mysql交互式模式:
        客戶端命令
            mysql> help
            mysql> \?
                \c
                \g
                \G
                \q
                \!
                \s
                \. /path/to/mysql_script.sql
        服務器端命令:須要命令結束符,默認爲分號(;)
            mysql> help contents

            mysql> help Keryword

    mysql命令行選項:
        --compress
        --database=, -D 
        -H, --html:輸出結果爲html格式的文檔
        -X, --xml: 輸出格式爲xml
        --sate-updates: 拒絕使用無where子句的update或delete命令;

    mysql命令提示符:
        mysql> 等待輸入命令
        ->
        '>
        ">
        `>
        /*> 

    mysql的快捷鍵:
        Ctrl + w: 刪除光標以前的單詞
        Ctrl + u: 刪除光標以前至命令行首的全部內容
        Ctrl + y: 粘貼使用Ctrl+w或Ctrl+u刪除的內容
        Ctrl + a: 移動光標至行首
        Ctrl + e: 移動光標至行尾

八、MySQL優化

MySQL優化須要在三個不一樣層次上協調進行:MySQL級別、OS級別和硬件級別。MySQL級別的優化包括表優化、查詢優化和MySQL服務器配置優化等,而MySQL的各類數據結構又最終做用於OS直至硬件設備,所以還須要瞭解每種結構對OS級別的資源的須要並最終致使的CPU和I/O操做等,並在此基礎上將CPU及I/O操做須要儘可能下降以提高其效率。

  • 數據庫層面的優化着眼點:

    一、是否正確設定了表結構的相關屬性,尤爲是每一個字段的字段類型是否爲最佳。
    二、是否爲高效進行查詢建立了合適的索引。
    三、是否爲每張表選用了合適的存儲引擎,並有效利用了選用的存儲引擎自己的優點和特性。
    四、是否基於存儲引擎爲表選用了合適的行格式(row format)。
    五、是否使用了合適的鎖策略,如在併發操做場景中使用共享鎖,而對較高優先級的需求使用獨佔鎖等。
    六、是否爲InnoDB的緩衝池、MyISAM的鍵緩存以及MySQL查詢緩存設定了合適大小的內存空間,以便可以存儲頻繁訪問的數據且又不會引發頁面換出。
  • 操做系統和硬件級別的優化着眼點:
    一、是否爲實際的工做負載選定了合適的CPU,如對於CPU密集型的應用場景要使用更快速度的CPU甚至更多數量的CPU,爲有着更多查詢的場景使用更多的CPU等。由於MySQL尚不能高效的運行於多CPU,而且其對CPU數量的支持也有着限制。通常來講,較新的版本能夠支持16至24顆CPU甚至更多。
    二、是否有着合適大小的物理內存,並經過合理的配置平衡內存和磁盤資源,下降甚至避免磁盤I/O。緩存能夠有效地延遲寫入、優化寫入,但並能消除寫入,並綜合考慮存儲空間的可擴展性等,爲業務選擇合理的外部存儲設備也是很是重要的工做。
    三、是否選擇了合適的網絡設備並正確地配置了網絡對總體系統系統也有着重大影響。延遲和帶寬是網絡鏈接的限制性因素,而常見的網絡問題如丟包等,便是很小的丟包率也會同意性能的顯著降低。而更重要的還有按需調整系統中關於網絡方面的設置,以高效處理大量的鏈接和小查詢。
    四、是否基於操做系統選擇了適用的文件系統。同時,關閉文件系統的某些特性如訪問時間和預讀行爲,並選擇合理的磁盤調度器一般都會給性能提高帶來幫助。
    五、MySQL爲響應每一個用戶鏈接使用一個單獨的線程,再加內部使用的線程、特殊目的線程以及其它任何由存儲引擎建立的線程等,MySQL須要對這些大量線程進行有效管理。Linux系統上的NPTL線程庫更爲輕量級也更有效率。MySQL 5.5引入了線程池插件,但其效用尚不明朗。

跟阿里雲數據庫大佬電話溝通 and Google解決方案 and 問羣裏大佬,總結以下(都是精華):
1.數據庫設計和表建立時就要考慮性能
2.sql的編寫須要注意優化
3.分區 【MySQL在5.1版引入的分區是一種簡單的水平拆分,用戶須要在建表的時候加上分區參數,對應用是透明的無需修改代碼】
4.分表 【分表就是把一張大表,按照如上過程都優化了,仍是查詢卡死,那就把這個表分紅多張表,把一次查詢分紅屢次查詢,而後把結果組合返回給用戶。】
5.分庫 【把一個數據庫分紅多個,建議作個讀寫分離就好了,真正的作分庫也會帶來大量的開發成本,得不償失!不推薦使用。】

第一優化sql和索引;
        第二加緩存,memcached,redis;
        第三以上都作了後,仍是慢,就作主從複製或主主複製,讀寫分離,能夠在應用層作,效率高,也能夠用三方工具,第三方工具推薦360的atlas,其它的要麼效率不高,要麼沒人維護;
        第四若是以上都作了仍是慢,不要想着去作切分,mysql自帶分區表,先試試這個,對你的應用是透明的,無需更改代碼,可是sql語句是須要針對分區表作優化的,sql條件中要帶上分區條件的列,從而使查詢定位到少許的分區上,不然就會掃描所有分區;
        第五若是以上都作了,那就先作垂直拆分,其實就是根據你模塊的耦合度,將一個大的系統分爲多個小的系統,也就是分佈式系統;
        第六纔是水平切分,針對數據量大的表,這一步最麻煩,最能考驗技術水平,要選擇一個合理的sharding key,爲了有好的查詢效率,表結構也要改動,作必定的冗餘,應用也要改,sql中儘可能帶sharding key,將數據定位到限定的表上去查,而不是掃描所有的表;

 
優化相關參數:
查詢mysql跑在哪顆cpu上一個進程只能跑在一個CPU上
mysql 詳解

查詢緩存流程圖:
mysql 詳解
開啓緩存
mysql > show variables like '%query%'; 查詢緩存
set global query_cache_size =16777216; 改查詢緩存
mysql 詳解
慢速查詢日誌
mysql 詳解
打開表動做緩存
mysql 詳解
鏈接數調整
mysql 詳解
緩存innidb表空間 【默認8M 理論越大越好 設置總體內存80%】
mysql 詳解
鏈接超時時間 【當網絡通訊狀況很差或後端機負載大時,這個數值往大調,否則會形成不少前端機連不上】
mysql 詳解
查看innodb事務日誌方式 【這個值對IO影響特別大,決定innodb事務日誌往磁盤寫的方式數值只有0 1 2 (建議改爲2)】
mysql 詳解

查詢相關的狀態變量
mysql 詳解
緩存命中率的評估:Qcache_hits/(Qcache_hits+Com_select)

九、總結

數據分析離不開SQL工具,SQL的使用能力是數據分析的一項基礎能力,這就是學習SQL最核心的緣由,只要你有從事數據分析的想法,就必須踏踏實實去學習。《大數據時代》是我看的第一本關於網絡趨勢的書,它從宏觀層面把握這個時代,從「大數據」這一時代特徵着手,講述了大數據對咱們生活,工做,乃至思惟的變革。具體包括:大數據的概念,它的價值,它帶來的轉變及轉變的方式,它的負面影響,這個時代的一系列規範等。在今天大數據盛行的時代,NoSQL:redis, mongodb, hbase, NewSQL:TiDB、關係型數據庫MySQL都在每一個業務層次發揮着重要的做用。無論是大數據仍是小數據,掌握一套數據管理系統是必要的,當下的MySQL在開源界仍是比較流行的,就連一些國企也開始在去IOE,因此仍是有深刻學習的必要,本着以溫故而知新的目的,把MySQL相關知識按部就班的梳理成新篇章。

相關文章
相關標籤/搜索