mysql壓縮表
① mysql的靜態表和動態表的區別,MyISAM和InnoDB的區別
MyISAM是MySQL的默認資料庫引擎(5.5版之前),由早期的ISAM(Indexed Sequential Access Method:有索引的順序訪問方法)所改良。雖然性能極佳,但卻有一個缺點:不支持事務處理(transaction)。不過,在這幾年的發展下,MySQL也導入了InnoDB(另一種資料庫引擎),銷咐以強化參考完整性與並發違規處理機制,後來就逐漸取代MyISAM。
InnoDB,是MySQL的資料庫引擎之一,為MySQL AB發布binary的標准之一。InnoDB由Innobase Oy公司所開發,2006年五月時由甲骨文公司並購。與傳統的ISAM與MyISAM相比,InnoDB的最大特色就是支持了ACID兼容的事務(Transaction)功能,類似於PostgreSQL。目前InnoDB採用雙軌制授權,一是GPL授權,另一是專有軟體授權。
MyISAM與InnoDB的區別是什麼?
1、 存儲結構
MyISAM:每個MyISAM在磁碟上存儲成三個文件。第一個文件的名字以表的名字開始,擴展名指出文件類型。.frm文件存儲表定義。數據文件的擴展名為.MYD (MYData)。索引文件的擴展名是.MYI (MYIndex)。
InnoDB:所有的表都保存在同一個數據文件中(也可能是多個文件,或者是獨立的表空間文件),InnoDB表的大小隻受限於操作系統文件的大小,一般為2GB。
2、 存儲空間
MyISAM:可被壓縮,存儲空間較小。支持三種不同的存儲格式:靜態表(默認,但是注意數據末尾不能有空格,會被去掉)、動態表、壓縮表。
InnoDB:需要更多的內存和存儲,它會在主內存中建立其專用的緩沖池用於高速緩沖數據和索引。
3、 可移植性、備份及恢復
MyISAM:數據是以文件的形式存儲,所以在跨平台的數據轉移中會很方便。在備份和恢復時可單獨針對某個表進行虧畝純操作。
InnoDB:免費的方案可以是拷貝數據文件、備份 binlog,或者用 mysqlmp,在數據量達到幾十G的時候就相對痛苦了。
4、 事務支持
MyISAM:強調的是性能,每次查詢具有原子性,其執行數度比InnoDB類型更快,但是不提供事務支持。
InnoDB:提供事務支持事務,外部鍵等高級資料庫功能。 具有事務(commit)、回滾(rollback)和崩潰修復能力(crash recovery capabilities)的事務安全(transaction-safe (ACID compliant))型表。
5、 AUTO_INCREMENT
MyISAM:可以和其他欄位一起建立聯合索引。引擎的自動增長列必須是索引,如果是組合索引,自動增長可以不是第一列,他可以根據前面幾列進行排序後遞增。
InnoDB:InnoDB中必須包含只有該欄位的索引。引擎的自動增長列必須是索引,如果是組合索引也必須是組合索引的第一列。
6、 表鎖差異
MyISAM:只支持表級鎖,用戶在操作myisam表時,select,update,delete,insert語句都會給表自動加鎖,如果加鎖以後的表滿足insert並發的情況下,可以在表的尾部插入新的數據。
InnoDB:支持事務和行級鎖,是innodb的最大特色。行鎖大幅度提高了多用戶並發操作的新能。但是InnoDB的行鎖,只是在WHERE的主鍵是有效的,非主鍵的WHERE都會鎖全表的。
7、 全文索引
MyISAM:支持 FULLTEXT類型的全文索引
InnoDB:不支持FULLTEXT類型的全文索引,但是innodb可以使用sphinx插件支持全文索引,並且效果更好。
8、 表主鍵
MyISAM:允許沒有任何索引和主鍵的表存在,索引都是保存行的地址。
InnoDB:如果沒有設定主鍵或者非空唯一索引,就會自動生成一個6位元組的主鍵(用戶不可見),數據是主索引的一部分,附加索引保存的是主索引的值。
9、 表的具體行數
MyISAM:保存有表的總行數,如果select count(*) from table;會直接取出出該值。
InnoDB:沒有保存表的總行數,如果使用select count(*) from table;就會遍歷整個表,消耗相當大,但是耐遲在加了wehre條件後,myisam和innodb處理的方式都一樣。
10、 CURD操作
MyISAM:如果執行大量的SELECT,MyISAM是更好的選擇。
InnoDB:如果你的數據執行大量的INSERT或UPDATE,出於性能方面的考慮,應該使用InnoDB表。DELETE 從性能上InnoDB更優,但DELETE FROM table時,InnoDB不會重新建立表,而是一行一行的刪除,在innodb上如果要清空保存有大量數據的表,最好使用truncate table這個命令。
11、 外鍵
MyISAM:不支持
InnoDB:支持
通過上述的分析,基本上可以考慮使用InnoDB來替代MyISAM引擎了,原因是InnoDB自身很多良好的特點,比如事務支持、存儲 過程、視圖、行級鎖定等等,在並發很多的情況下,相信InnoDB的表現肯定要比MyISAM強很多。另外,任何一種表都不是萬能的,只用恰當的針對業務類型來選擇合適的表類型,才能最大的發揮MySQL的性能優勢。如果不是很復雜的Web應用,非關鍵應用,還是可以繼續考慮MyISAM的,這個具體情況可以自己斟酌。
② 技術分享 | MySQL binlog 壓縮功能對性能的影響
之前有做過一個 binlog 壓縮能節約多少空間的測試,效果上看還是比較理想的,可以節約一半以上的空間。但是這個又引出了一個新的問題,那就是這個功能對性能有多大影響呢?於是我又在測試環境試了一下,測試環境的物理配置如下。
根據之前的經驗這套測試環境閉指姿在 120 個表 + 240 個並發的情況,可以逗歲取得一個性能上的極大值;所以在這里就直接使用這個作為測試壓力。
第一步:安裝。
第二步:創建測試用戶。
第三步:填充數據並進行壓力測試。
性能表現。
資源消耗情況。
第一步:安裝。
第二步:創建測試用戶。
第三步:填充數據並進行壓力測試。
性能表現。
資源消耗轎絕情況。
第一步: 關閉 binlog 壓縮功能。
第二步:進行壓力測試。
性能表現。
資源消耗情況。
開啟 binlog 壓縮會對性能有影響,大概會讓性能下降 1%,cpu 多消耗 1%。
③ Mysql存儲引擎Myisam小結
myisam在mysql5.5之前是默認存儲引擎,從5.5開始mysql的默認存儲引擎為虧寬辯innodb.目前mysql版本myisam仍然有廣泛的應用.mysql的一些系統表和臨時表存儲引擎仍然使用的myisam.這里的臨時表指的是在查詢過程中對查詢的數據進行排序,分組等操作,數據量超過一定數量時,由查詢優化器建立的臨時表.
myisam每個表都有三個文件組成:
.frm 表結構描述
.MYD 存儲數據
.MYI 存儲索引
myisam存儲引擎的鎖級別為表級鎖,myisam為表級讀共享寫獨占鎖.myisam讀並不會完全阻塞寫,myisam允許在讀的同時在表的後面追加對應的數據.concurrent_insert控制對應的並發性.
concurrent_insert可以設置為以下3個值:
在5.0之前,myisam只支持文件大小為4G的文件,再次之後支持256TB大小的文件.如果表要大於銷缺4G,需要設置MAX_ROWS和AVG_ROW_LENGTH的值.
相對於innodb存儲引擎來說myisam佔用的表空間更加少。myisam支持通過myisampack對單個表做進一步壓縮。通過myisampack進行壓縮,myisampack能過將數據壓縮40%~70%。但是通過myisampack壓縮後的數據該表巧返將變成只讀。壓縮後需要對該表進行檢查,使用工具myisamchk。
myisam存儲引擎不支持事務。update後無需commit將會自動提交,也無法回滾。正是如此,myisam沒有redo log以及undo log文件。在遷移數據對應的表的時候,只需要將對應的表拷貝到目標機器上就可以使用了。但是由於沒有redo log和undo log,這樣容易造成表損壞。
通過check table tablename和repair table tablename兩條命令表進行修護。
myisam含有一些空間函數。一些地理信息系統的空間應用需要使用這種類型的存儲引擎。
④ mysql壓縮包怎麼安裝
1、首先解壓縮下載的安裝包。
2、解壓之後可以將該文件夾改名,例如mysql,放到合適的位置,比如放到C:\mysql路徑中。
3、配置環境:
我的電腦->屬性->高級->環境變數
選擇PATH,在其後面添加: mysql\bin文件夾的路徑 (如:C:\mysql\bin)
PATH=.......; C:\mysql\bin (在PATH最後添加分號;並填寫路徑)
4.修改mysql文件夾下配置文件,默認文件夾內有個名為my-default的配置文件,將其修改為my
再在其中修改或添加配置:
[mysqld]
basedir= "C:\mysql\"(mysql所在目錄)
datadir= "C:\mysqldata\" (mysql data所在目錄,需要在C盤下創建文件夾mysqldata)
在C盤下新建mysqldata文件夾。
5.以管理員身份運行cmd,執行命令mysqld --initialize 進行初始化創建1個文本文件,並將下述命令置於單一行中:SET PASSWORD FOR 'root'@'localhost' = PASSWORD('MyNewPassword');用任意名稱保存該文件。在本例中,該文件為C:\mysqldata\init.txt。在命令行中執行mysqld --init-file=C:\mysqldata\init.txt
此命令會不會自動退出,打開另一個cmd(不需要管理員許可權),執行命令mysql -u root -p,按回車鍵,輸入密碼為MyNewPassword,即可進入mysql 。
退出mysqld 服務可以通過任務管理器結束mysqld.exe進程。
6.以管理員身份運行cmd,輸入mysqld --install 安裝mysql服務。
在計算機管理服務中會出現MySQL服務,以後想進入mysql,直接啟動MySQL服務即可。
啟動MySQL 會出現錯誤:
報錯的原因是無法找到Mysql執行文件,通過修改注冊表進行處理,到注冊表裡HKEY_LOCAL_MECHINE---SYSTEM ---CurrentControlSet---services 更改查找MySQL項值,然後改路徑。
通過"win"鍵+R鍵一起按,調出「運行」窗口,輸入regedit調出注冊表
找到 HKEY_LOCAL_MECHINE---SYSTEM ---CurrentControlSet ---services
在services中找到MySQL
更改ImagePath 值為mysql\bin所在路徑,例如本例中:"C:\mysql\bin\mysqld" MySQL
7.通過命令行執行net start mysql 或者是在計算機管理中的服務下啟動MySQL,然後在命令行下輸入mysql -u root -p 進入。
⑤ 如何使用mysqlmp進行壓縮備份
通用規律只有使用 --all-databases (-A) 會 ERROR 1356,那就看看他到底備份了什麼東西。於是喊上同事一起 less 看了下,上下掃了兩眼。突然發現:1. 備份 SQL 文件里 DROP 掉了 mysql.proc;2. 後CREATE了一個新的 mysql.proc;3. LOCK TABLES 和 UNLOCK TABLES 中間居然沒有備份 CREATE ROUTINE 任何數據?這不就是相當於每次導入全備都給我一個沒有任何 sys schema routines 的全新 mysql.proc 表?那這不就異常的尷尬?
---- Table structure for table `proc`--
---- Dumping data for table `proc`-
真相大白在官方文檔【sys-schema-usage】官方文檔明確的告訴我們不會備份 sys 庫。但在使用 mysqlmp 在執行 --all-databases 會清空 mysql.proc 導致 sys 無法正常使用;這是一個 BUG,並且只存在於 MySQL 5.7.x !
1、mysql_upgrade install or upgrade sys schema
這個方案適用於 sys 庫已經因為 mysqlmp 導入而損壞的情況下使用。
注意:mysql_upgrade 在修理 sys 庫的同時,還修理 mysql 庫和用戶庫表(期間加鎖且速度一般),有極小可能會誤傷;使用 mysql_upgrade 的時候要加上 --upgrade-system-tables,不然會掃描用戶庫表。
2、全備時同時備份 sys 庫
這個方案適用於需要還原的資料庫,sys 庫也不太正常的情況下使用;在全備後額外再備份一份 sys 庫用於修復。
注意:不適用於做主從時使用它。
3、使用 databases 全備
這個方案適用於所有場景的全備需求,100% 安全。
4、使用 mysql-sys 開源代碼
如果你的資料庫 sys 全部中招了,又是生產庫。那你只能用這個方法;
mysql-sys:https://github.com/mysql/mysql-sys
中記錄了 sys 庫的創建語句將文件下載到本地,然後根據資料庫版本,執行以下命令即可。
⑥ mysql運維管理(八):合格的運維管理員必須掌握的常用工具
在MySQL日常運維工作中,經常會用到各種管理工具,這些工具屬於mysql自帶的管理工具,存儲在mysql目錄下的bin目錄中,例如對象查看,備份,日誌分析等,熟練使用是運維開發人員的必備工作,這些工具參數很多,這里介紹常用選項,更多詳細可參考幫助文件。
在mysql工具集中,管理員使用最頻繁的就是mysql命令了,它是連接資料庫的客戶端工具,類似oracle中的sqlplus,通過它可以進入mysql控制台界面。在大部分情況下,使用簡單,命令語法如下:
常用選項:選項一般有兩種表達方式,一基滑種是"-"+選項單詞縮寫和選項值;另一種是「--」+選項的完整單詞「=」選項實際值。例如我們連接資料庫的兩種尺知命令如下:
myisampack是一個表壓縮工具,它對MyISAM存儲引擎表能進行高度壓縮,可以很大的節省磁碟空間,但是壓縮後的表只能讀,不能寫,不能進行DML操作,所以它的使用場景一般是歸檔 歷史 數據。命令如下:
當對一個壓縮表進行增加操作時會報一個錯誤:ERROR 1036 Table is read only,但時對查詢和統計時可以正常操作的。
mysqladmin是一個對資料庫進行管理操作的客戶端工具,可用來檢查伺服器是否可用、顯示資料庫版本號和狀態,還可以直接新增一個資料庫,也可對資料庫進行關閉,功能和mysql類似,它的參數和mysql差異不大,命令如下:
它還可以修改root密碼,命令如下
MySQL自帶的mysqlbinlog工具的作用是解析二進制binlog的日誌內容,把二進制數據還原成mysql可以執行的SQL語句。我有篇文章專門介紹該工具的使用,請具體參考:
傳送門:mysql運維管理(七):使用Mysqlbinlog工具恢復增量數據
mysqlcheck工具可以用來檢查和修復MyISAM存儲引擎的表,還能做優化的工作,例如check、repair、analyze、optimize等等功能。具體命令如下:
注意,如果是innodb引擎的表,不能用上述優化工具。
mysqlmp工具用來邏輯備份資料庫,或者數據遷移。該工具是最常用的備份工具。
我有篇文章專門介紹該工具的使用,請具體參考:
傳送門:mysql運維管理(五):掌握MySQLmp邏輯備份工具使用
它是數據導入工具,專門用來處理mysqlmp 加-T選項後導出的文本文件,基本用法很簡單,命令如下:
客戶端對象查找工具,用來查找資料庫,資料庫的表,表中列或者索引,具體使用命令如下:
不加任何選項,默認顯示所有資料庫。
常用參數:
--count ,用來顯示資料庫和表的統計信息,不指定資料庫的話,顯示所有庫信息
-k或者--keys,用來顯示指定表中所有索引,例如查看employees庫中employees表的索搏困臘引信息,
在使用mysql使用過程中,會經常出現錯誤,錯誤信息都會帶有一個編碼,具體編碼代表什麼意思,就需要perror來查看。用法很簡單:
舉個例子,我們故意寫錯一個查詢語句,例如:
現在有一個編碼1054,我們可以用perror查看下
結果跟用工具顯示的內容差不多,當然第三方工具也會顯示錯誤信息。
本章做了一個常用工具的使用匯總,並舉例說明了基本用法,熟練使用是每個運維人員必修內容,當然還有很多參數沒有一一列舉,可以參考相關幫助文檔。
⑦ 如何壓縮Mysql資料庫
壓縮表從名字上來看,簡單理解為壓縮後的表,也就是把原始表根據一定的壓縮演算法按照一定的壓縮比率壓縮後生成的表。
1.1 壓縮能力強的產品
表壓縮後從磁碟佔用上看要比原始表要小很多。如果你熟悉列式資料庫,那對這個概念一定不陌生。比如,基於 PostgreSQL 的列式資料庫 Greenplum;早期基於 MySQL 的列式資料庫 inforbright;或者 Percona 的產品 tokudb 等,都是有壓縮能力非常強的資料庫產品。
1.2 為什麼要用壓縮表?
情景一:磁碟大小為 1T,不算其他的空間佔用,只能存放 10 張 100G 大小的表。如果這些表以一定的比率壓縮後,比如每張表從 100G 壓縮到 10G,那同樣的磁碟可以存放 100 張表,表的容量是原來的 10 倍。情景二:默認 MySQL 頁大小 16K,而 OS 文件系統一般塊大小為 4K,所以在 MySQL 在刷臟頁的過程中,有一定的概率出現頁沒寫全而導致數據壞掉的情形。比如 16K 的頁寫了 12K,剩下 4K 沒寫成功,導致 MySQL 頁數據損壞。這個時候就算通過 Redo Log 也恢復不了,因為幾乎有所有的關系資料庫採用的 Redo Log 都記錄了數據頁的偏移量,此時就算通過 Redo Log 恢復後,數據也是錯誤的。所以 MySQL 在刷臟數據之前,會把這部分數據先寫入共享表空間里的 DOUBLE WRITE BUFFER 區域來避免這種異常。此時如果 MySQL 採用壓縮表,並且每張表頁大小和磁碟塊大小一致,比如也是 4K,那 DOUBLE WRITE BUFFER 就可以不需要,這部分開銷就可以規避掉了。查看文件系統的塊大小:
root@ytt-pc:/home/ytt#tune2fs-l/dev/mapper/ytt--pc--vg-root|grep-i'blocksize'Block size: 4096
- 1.3 壓縮表的優勢
- 1.4 壓縮表的缺陷
- 1.5 MySQL 支持的壓縮演算法
壓縮表的優點非常明顯,佔用磁碟空間小!由於佔用空間小,從磁碟置換到內存以及之後經過網路傳輸都非常節省資源。
簡單來講:節省磁碟 IO,減少網路 IO。
當然壓縮表也有缺點,壓縮表的寫入(INSERT,UPDATE,DELETE)比普通表要消耗更多的 CPU 資源。
壓縮表的寫入涉及到解壓數據,更新數據,再壓縮數據,比普通表多了解壓和再壓縮兩個步驟,壓縮和解壓縮需要消耗一定的 CPU 資源。所以需要選擇一個比較優化的壓縮演算法。
這塊是 MySQL 所有涉及到壓縮的基礎,不僅僅用於壓縮表,也用於其它地方。比如客戶端請求到 MySQL 服務端的數據壓縮;主從之間的壓縮傳輸;利用克隆插件來復制資料庫操作的壓縮傳輸等等。
從下面結果可以看到 MySQL 支持的壓縮演算法為 zlib 和 zstd,MySQL 默認壓縮演算法為 zlib,當然你也可以選擇非 zlib 演算法,比如 zstd。至於哪種壓縮演算法最優,暫時沒辦法簡單量化,依賴表中的數據分布或者業務請求。
⑧ mysql存儲引擎類型有哪些
1、MyISAM
使用這個存儲引擎,每個MyISAM在磁碟上存儲成三個文件。
(1)frm文件:存儲表的定義數據
(2)MYD文件:存放表具體記錄的數據
(3)MYI文件:存儲索引
frm和MYI可以存放在不同的目錄下。MYI文件用來存儲索引,但僅保存記錄所在頁的指針,索引的結構是B+樹結構。下面這張圖就是MYI文件保存的機制:
從這張圖可以發現,這個存儲引擎通過MYI的B+樹結構來查找記錄頁,再根據記錄頁查找記錄。並且支持全文索引、B樹索引和數據壓縮。
支持數據的類型也有三種:
(1)靜態固定長度表
這種方式的優點在於存儲速度非常快,容易發生緩存,而且表發生損壞後也容易修復。缺點是占空間。這也是默認的存儲格式。
(2)動態可變長表
優點是節省空間,但是一旦出錯恢復起來比較麻煩。
(3)壓縮表
上面說到支持數據壓縮,說明肯定也支持這個格式。在數據文件發生錯誤時候,可以使用check table工具來檢查,而且還可以使用repair table工具來恢復。
有一個重要的特點那就是不支持事務,但是這也意味著他的存儲速度更快,如果你的讀寫操作允許有錯誤數據的話,只是追求速度,可以選擇這個存儲引擎。
2、InnoDB
InnoDB是默認的資料庫存儲引擎,他的主要特點有:
(1)可以通過自動增長列,方法是auto_increment。
(2)支持事務。默認的事務隔離級別為可重復度,通過MVCC(並發版本控制)來實現的。
(3)使用的鎖粒度為行級鎖,可以支持更高的並發;
(4)支持外鍵約束;外鍵約束其實降低了表的查詢速度,但是增加了表之間的耦合度。
(5)配合一些熱備工具可以支持在線熱備份;
(6)在InnoDB中存在著緩沖管理,通過緩沖池,將索引和數據全部緩存起來,加快查詢的速度;
(7)對於InnoDB類型的表,其數據的物理組織形式是聚簇表。所有的數據按照主鍵來組織。數據和索引放在一塊,都位於B+數的葉子節點上;
當然InnoDB的存儲表和索引也有下面兩種形式:
(1)使用共享表空間存儲:所有的表和索引存放在同一個表空間中。
(2)使用多表空間存儲:表結構放在frm文件,數據和索引放在IBD文件中。分區表的話,每個分區對應單獨的IBD文件,分區表的定義可以查看我的其他文章。使用分區表的好處在於提升查詢效率。
對於InnoDB來說,最大的特點在於支持事務。但是這是以損失效率來換取的。
3、Memory
將數據存在內存,為了提高數據的訪問速度,每一個表實際上和一個磁碟文件關聯。文件是frm。
(1)支持的數據類型有限制,比如:不支持TEXT和BLOB類型,對於字元串類型的數據,只支持固定長度的行,VARCHAR會被自動存儲為CHAR類型;
(2)支持的鎖粒度為表級鎖。所以,在訪問量比較大時,表級鎖會成為MEMORY存儲引擎的瓶頸;
(3)由於數據是存放在內存中,一旦伺服器出現故障,數據都會丟失;
(4)查詢的時候,如果有用到臨時表,而且臨時表中有BLOB,TEXT類型的欄位,那麼這個臨時表就會轉化為MyISAM類型的表,性能會急劇降低;
(5)默認使用hash索引。
(6)如果一個內部表很大,會轉化為磁碟表。
在這里只是給出3個常見的存儲引擎。使用哪一種引擎需要靈活選擇,一個資料庫中多個表可以使用不同引擎以滿足各種性能和實際需求,使用合適的存儲引擎,將會提高整個資料庫的性能
⑨ 如何設置mysql innodb 表的壓縮
設置innodb 表的 壓縮
第埋碧一,mysql的版本需搏梁要大於基液運5.5
第二,設置innodb_file_format=barracuda
第三,create table或者alter talble 增加 ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8;(默認的key_block_size=16)
根據經驗,一般壓縮比例可以達到30%-40%
⑩ MySQL簡單介紹——換個角度認識MySQL
1、InnoDB存儲引擎
Mysql版本>=5.5 默認的存儲引擎,MySQL推薦使用的存儲引擎。支持事務,行級鎖定,外鍵約束。事務安全型存儲引擎。更加註重數據的完整性和安全性。
存儲格式 : 數據,索引集中存儲,存儲於同一個表空間文件中。
InnoDB的行鎖模式及其加鎖方法: InnoDB中有以下兩種類型的行鎖:共享鎖(讀鎖: 允許事務對一條行數據進行讀取)和 互斥鎖(寫鎖: 允許事務對一條行數據進行刪除或更新), 對於update,insert,delete語句,InnoDB會自動給設計的數據集加互斥鎖,對於普通的select語句,InnoDB不會加任何鎖。
InnoDB行鎖的實現方式: InnoDB行鎖是通過給索引上的索引項加鎖來實現的,如果沒有索引,InnoDB將通過隱藏的聚簇索引來對記錄加鎖。InnoDB這種行鎖實現特點意味著:如果不通過索引條件檢索數據,那麼InnoDB將對表中的所有記錄加鎖,實際效果跟表鎖一樣。
(1)在不通過索引條件查詢時,InnoDB會鎖定表中的所有記錄。
(2)Mysql的行鎖是針對索引加的鎖,不是針對記錄加的鎖,所以雖然是訪問不同行的記錄,但是如果使用相同的索引鍵,是會出現沖突的。
(3)當表有多個索引的時候,不同的事務可以使用不同的索引鎖定不同的行,但都是通過行鎖來對數據加鎖。
優點:
1、支持事務處理、ACID事務特性;
2、實現了SQL標準的四種隔離級別( 原子性( Atomicity )、一致性( Consistency )、隔離性(Isolation )和持續性(Durability ));
3、支持行級鎖和外鍵約束;
4、可以利用事務日誌進行數據恢復。
5、鎖級別為行鎖,行鎖優點是適用於高並發的頻繁表修改,高並發是性能優於 MyISAM。缺點是系統消耗較大。
6、索引不僅緩存自身,也緩存數據,相比 MyISAM 需要更大的內存。
缺點:
因為它沒有保存表的行數,當使用COUNT統計時會掃描全表。
使用場景:
(1)可靠性要求比較高,或者要求事務;(2)表更新和查詢都相當的頻繁,並且表鎖定的機會比較大的情況。
2、 MyISAM存儲引擎
MySQL<= 5.5 MySQL默認的存儲引擎。ISAM:Indexed Sequential Access Method(索引順序存取方法)的縮寫,是一種文件系統。擅長與處理,高速讀與寫。
功能:
(1)支持數據壓縮存儲,但壓縮後的表變成了只讀表,不可寫;如果需要更新數據,則需要先解壓後更新。
(2)支持表級鎖定,不支持高並發;
(3)支持並發插入。寫操作中的插入操作,不會阻塞讀操作(其他操作);
優點:
1.高性能讀取;
2.因為它保存了表的行數,當使用COUNT統計時不會掃描全表;
缺點:
1、鎖級別為表鎖,表鎖優點是開銷小,加鎖快;缺點是鎖粒度大,發生鎖沖動概率較高,容納並發能力低,這個引擎適合查詢為主的業務。
2、此引擎不支持事務,也不支持外鍵。
3、INSERT和UPDATE操作需要鎖定整個表;
使用場景:
(1)做很多count 的計算;(2)插入不頻繁,查詢非常頻繁;(3)沒有事務。
InnoDB和MyISAM一些細節上的差別:
1、InnoDB不支持FULLTEXT類型的索引,MySQL5.6之後已經支持(實驗性)。
2、InnoDB中不保存表的 具體行數,也就是說,執行select count() from table時,InnoDB要掃描一遍整個表來計算有多少行,但是MyISAM只要簡單的讀出保存好的行數即可。注意的是,當count()語句包含 where條件時,兩種表的操作是一樣的。
3、對於AUTO_INCREMENT類型的欄位,InnoDB中必須包含只有該欄位的索引,但是在MyISAM表中,可以和其他欄位一起建立聯合索引。
4、DELETE FROM table時,InnoDB不會重新建立表,而是一行一行的刪除。
5、LOAD TABLE FROM MASTER操作對InnoDB是不起作用的,解決方法是首先把InnoDB表改成MyISAM表,導入數據後再改成InnoDB表,但是對於使用的額外的InnoDB特性(例如外鍵)的表不適用。
6、另外,InnoDB表的行鎖也不是絕對的,如果在執行一個SQL語句時MySQL不能確定要掃描的范圍,InnoDB表同樣會鎖全表。
1.索引概述
利用關鍵字,就是記錄的部分數據(某個欄位,某些欄位,某個欄位的一部分),建立與記錄位置的對應關系,就是索引。索引的關鍵字一定是排序的。索引本質上是表欄位的有序子集,它是提高查詢速度最有效的方法。一個沒有建立任何索引的表,就相當於一本沒有目錄的書,在每次查詢時就會進行全表掃描,這樣會導致查詢效率極低、速度也極慢。如果建立索引,那麼就好比一本添加的目錄,通過目錄的指引,迅速翻閱到指定的章節,提升的查詢性能,節約了查詢資源。
2.索引種類
從索引的定義方式和用途中來看:主鍵索引,唯一索引,普通索引,全文索引。
無論任何類型,都是通過建立關鍵字與位置的對應關系來實現的。索引是通過關鍵字找對應的記錄的地址。
以上類型的差異:對索引關鍵字的要求不同。
關鍵字:記錄的部分數據(某個欄位,某些欄位,某個欄位的一部分)。
普通索引,index:對關鍵字沒有要求。
唯一索引,unique index:要求關鍵字不能重復。同時增加唯一約束。
主鍵索引,primary key:要求關鍵字不能重復,也不能為NULL。同時增加主鍵約束。
全文索引,fulltext key:關鍵字的來源不是所有欄位的數據,而是從欄位中提取的特別關鍵詞。
PS:這里主鍵索引和唯一索引的區別在於:主鍵索引不能為空值,唯一索引允許空值;主鍵索引在一張表內只能創建一個,唯一索引可以創建多個。主鍵索引肯定是唯一索引,但唯一索引不一定是主鍵索引。
3.索引原則
如果索引不遵循使用原則,則可能導致索引無效。
(1)列獨立
如果需要某個欄位上使用索引,則需要在欄位參與的表達中,保證欄位獨立在一側。否則索引不會用到索引, 例如這條sql就不會用到索引:select * from A where id+1=10;
(2)左原則
Like:匹配模式必須要左邊確定不能以通配符開頭。例如:select * from A where name like '%小明%' ,不會用到索引,而select * from A where name like '小明%' 就可以用到索引(name欄位有建立索引),如果業務上需要用到'%小明%'這種方式,有兩種方法:1.可以考慮全文索引,但mysql的全文索引不支持中文;2.只查詢索引列或主鍵列,例如:select name from A where name like '%小明%' 或 select id from A where name like '%小明%' 或 select id,name from A where name like '%小明%' 這三種情況都會用到name的索引;
復合索引:一個索引關聯多個欄位,僅僅針對左邊欄位有效果,添加復合索引時,第一個欄位很重要,只有包含第一個欄位作為查詢條件的情況才會使用復合索引(必須用到建索引時選擇的第一個欄位作為查詢條件,其他欄位的順序無關),而且查詢條件只能出現and拼接,不能用or,否則則無法使用索引.
(3)OR的使用
必須要保證 OR 兩端的條件都存在可以用的索引,該查詢才可以使用索引。
(4)MySQL智能選擇
即使滿足了上面說原則,MySQL也能棄用索引,例如:select * from A where id > 1;這里棄用索引的主要原因:查詢即使使用索引,會導致出現大量的隨機IO,相對於從數據記錄的第一條遍歷到最後一條的順序IO開銷,還要大。
4.索引的使用場景
(1)索引檢索:檢索數據時使用索引。
(2)索引排序: 如果order by 排序需要的欄位上存在索引,則可能使用到索引。
(3)索引覆蓋: 索引擁有的關鍵字內容,覆蓋了查詢所需要的全部數據,此時,就不需要在數據區獲取數據,僅僅在索引區即可。覆蓋就是直接在索引區獲取內容,而不需要在數據區獲取。例如: select name from A where name like '小明%';
建立索引索引時,不能僅僅考慮where檢索,同時考慮其他的使用場景。(在所有的where欄位上增加索引,就是不合理的)
5.前綴索引
前綴索引是建立索引關鍵字一種方案。通常會使用欄位的整體作為索引關鍵字。有時,即使使用欄位前部分數據,也可以去識別某些記錄。就比如一個班級里,我要找王xx,假如姓王的只有1個人,那麼就可以建一個關鍵字為'王'的前綴索引。語法:Index `index_name` (`index_field`(N))使用index_name前N個字元建立的索引。
6.索引失效
(1) 應盡量避免在 where 子句中使用 != 或 > 操作符,否則將引擎放棄使用索引而進行全表掃描;
(2) 應盡量避免在 where 子句中使用 or 來連接條件,如果一個欄位有索引,一個欄位沒有索引,將導致引擎放棄使用索引而進行全表掃描;
(3) 應盡量避免在 where 子句中對欄位進行 null 值判斷,否則將導致引擎放棄使用索引而進行全表掃描;
(4)應盡量避免在 where 子句中對欄位進行表達式操作,這將導致引擎放棄使用索引而進行全表掃描;如select id from t where num/2 = 100;
(5) 應盡量避免在where子句中對欄位進行函數操作,這將導致引擎放棄使用索引而進行全表掃描;如:select id from t where substring(name,1,3) = 』abc』 ;
(6)應盡量避免在where子句中對欄位進行類型轉換,這將導致引擎放棄使用索引而進行全表掃描; 如果列類型是字元串,那一定要在條件中將數據使用引號引用起來,如select id from t where id = 1;如果id欄位在表設計中是varchar類型,那麼即使id列上存的是數字,在查詢時也一定要用varchar去匹配,sql應改為select id from t where id = '1';
(7)應盡量避免在where子句中單獨引用復合索引里非第一位置的索引;
join 的兩種演算法:BNL 和 NLJ
NLJ(Nested Loop Join)嵌套循環演算法;以如下 SQL 為例:
select * from t1 join t2 on t1.a=t2.a
SQL 執行時內部流程是這樣的:
1. 先從 t1(假設這里 t1 被選為驅動表)中取出一行數據 X;
2. 從 X 中取出關聯欄位 a 值,去 t2 中進行查找,滿足條件的行取出;
3. 重復1、2步驟,直到表 t1 最後一行循環結束。
這就是一個嵌套循環的過程,如果在被驅動表上查找數據時可以使用索引,總的對比計算次數等於驅動表滿足 where 條件的行數。假設這里 t1、t2都是1萬行,則只需要 1萬次計算,這里用到的是Index Nested-Loops Join(INLJ,基於索引的嵌套循環聯接)。
如果 t1、t2 的 a 欄位都沒有索引,還按照上述的嵌套循環流程查找數據呢?每次在被驅動表上查找數據時都是一次全表掃描,要做1萬次全表掃描,掃描行數等於 1萬+1萬*1萬,這個效率很低,如果錶行數更多,掃描行數動輒幾百億,所以優化器肯定不會使用這樣的演算法,而是選擇 BNL 演算法;
BNLJ(Block Nested Loop Join)塊嵌套循環演算法;
1. 把 t1 表(假設這里 t1 被選為驅動表)滿足條件的數據全部取出放到線程的 join buffer 中;
2. 每次取 t2 表一行數據,去 joinbuffer 中進行查找,滿足條件的行取出,直到表 t2 最後一行循環結束。
這個演算法下,執行計劃的 Extra 中會出現 Using join buffer(Block Nested Loop),t1、t2 都做了一次全表掃描,總的掃描行數等於 1萬+1萬。但是由於 joinbuffer 維護的是一個無序數組,每次在 joinbuffer 中查找都要遍歷所有行,總的內存計算次數等於1萬*1萬。另外如果 joinbuffer 不夠大放不下驅動表的數據,則要分多次執行上面的流程,會導致被驅動表也做多次全表掃描。
BNLJ相對於NLJ的優點在於,驅動層可以先將部分數據載入進buffer,這種方法的直接影響就是將大大減少內層循環的次數,提高join的效率。
例如:
如果內層循環有100條記錄,外層循環也有100條記錄,這樣的話,每次外層循環先將10條記錄放到buffer中,內層循環的100條記錄每條與這個buffer中的10條記錄進行匹配,只需要匹配內層循環總記錄數次即可結束一次循環(在這里,即只需要匹配100次即可結束),然後將匹配成功的記錄連接後放入結果集中,接著,外層循環繼續向buffer中放入10條記錄,同理進行匹配,並將成功的記錄連接後放入結果集。後續循環以此類推,直到循環結束,將結果集發給client為止。
可以發現,若用NLJ,則需要100 * 100次才可結束,BNLJ則需要100 / block_size * 100 = 10 * 100次就可結束,大大減少了循環次數。
JOIN 按照功能大致分為如下三類:
JOIN、STRAIGHT_JOIN、INNER JOIN(內連接,或等值連接):取得兩個表中存在連接匹配關系的記錄。
LEFT JOIN(左連接):取得左表(table1)完全記錄,即是右表(table2)並無對應匹配記錄。
RIGHT JOIN(右連接):與 LEFT JOIN 相反,取得右表(table2)完全記錄,即是左表(table1)並無匹配對應記錄。
注意:mysql不支持Full join,不過可以通過UNION 關鍵字來合並 LEFT JOIN 與 RIGHT JOIN來模擬FULL join。
mysql 多表連接查詢方式,因為mysql只支持NLJ演算法,所以如果是小表驅動大表則效率更高;反之則效率下降;因此mysql對內連接或等值連接的方式做了一個優化,會去判斷join表的數據行大小,然後取數據行小的表為驅動表。
INNER JOIN、JOIN、WHERE等值連接和STRAIGHT_JOIN都能表示內連接,那平時如何選擇呢?一般情況下用INNER JOIN、JOIN或者WHERE等值連接,因為MySQL 會按照"小表驅動大表的策略"進行優化。當出現需要排序時,才考慮用STRAIGHT_JOIN指定某張表為驅動表。
兩表JOIN優化
a.當無order by條件時,根據實際情況,使用left/right/inner join即可,根據explain優化 ;
b.當有order by條件時,如select * from a inner join b where 1=1 and other condition order by a.col;使用explain解釋語句;
1)如果第一行的驅動表為a,則效率會非常高,無需優化;
2)否則,因為只能對驅動表欄位直接排序的緣故,會出現using temporary,所以此時需要使用STRAIGHT_JOIN明確a為驅動表,來達到使用a.col上index的優化目的;或者使用left join且Where條件中不含b的過濾條件,此時的結果集為a的全集,而STRAIGHT_JOIN為inner join且使用a作為驅動表。註:使用STRAIGHT_JOIN雖然不會using temporary,但也不是一定就能提高效率,如果a表數據遠遠超過b表,那麼有可能使用STRAIGHT_JOIN時比原來的sql效率更低,所以怎麼使用STRAIGHT_JOIN,還是要視情況而定。
在使用left join(或right join)時,應該清楚的知道以下幾點:
(1). on與 where的執行順序
ON 條件(「A LEFT JOIN B ON 條件表達式」中的ON)用來決定如何從 B 表中檢索數據行。如果 B 表中沒有任何一行數據匹配 ON 的條件,將會額外生成一行所有列為 NULL 的數據,在匹配階段 WHERE 子句的條件都不會被使用。僅在匹配階段完成以後,WHERE 子句條件才會被使用。它將從匹配階段產生的數據中檢索過濾。
所以我們要注意:在使用Left (right) join的時候,一定要在先給出盡可能多的匹配滿足條件,減少Where的執行。
(2).注意ON 子句和 WHERE 子句的不同
即使右表的數據不滿足ON後面的條件,也會在結果集拼接一條為NULL的數據行,但WHERE後面的條件不一樣,右表不滿足WHERE的條件,左表關聯的數據也會被過濾掉。
(3).盡量避免子查詢,而用join
往往性能這玩意兒,更多時候體現在數據量比較大的時候,此時,我們應該避免復雜的子查詢。
(1)in 和 not in 要慎用,如:select id from t where num in(1,2,3)對於連續的數值,能用 between 就不要用 in:select id from t where num between 1 and 3很多時候用 exists 代替 in 是一個好的選擇:select num from a where num in(select num from b)用下面的語句替換:select num from a where exists(select 1 from b where num=a.num)
(2)Update 語句,如果只更改1、2個欄位,不要Update全部欄位,否則頻繁調用會引起明顯的性能消耗,同時帶來大量日誌。
(3)join語句,MySQL裡面的join是用小表去驅動大表,而由於MySQL join實現的原理就是做循環,比如left join就是對左邊的數據進行循環去驅動右邊的表,左邊有m條記錄匹配,右邊有n條記錄那麼就是做m次循環,每次掃描n行數據,總掃面行數是m*n行數據。左邊返回的結果集的大小就決定了循環的次數,故單純的用小表去驅動大表不一定的正確的,小表的結果集可能也大於大表的結果集,所以寫join的時候盡可能的先估計兩張表的可能結果集,用小結果集去驅動大結果集.值得注意的是在使用left/right join的時候,從表的條件應寫在on之後,主表應寫在where之後.否則MySQL會當作普通的連表查詢;
(4)select count(*) from table;這樣不帶任何條件的count會引起全表掃描,並且沒有任何業務意義,是一定要杜絕的;
(5)select * from t 這種語句要盡量避免,使用具體的欄位代替*,更有實際意義,需要什麼欄位就返回什麼欄位;
(6)數據量大的情況下,limit要慎用,因為使用limit m,n方式分頁時,mysql每次都是查詢前m+n條,然後舍棄前m條,所以m越大,偏移量越大,性能就越差。比如:select * from A limit 1000000,20這鍾,查詢效率就會非常低,當分頁的頁數大於一定的數量之後,就可以換種方式來分頁:select * from A a join (select id from A limit 1000000,20) b on a.id=b.id;