# 數據庫存儲引擎與SQL優化筆記mysql
[TOC]sql
## Mysql分層,存儲引擎數據庫
數據庫從上到下設計模式
- 鏈接層 (提供與客戶端鏈接的服務)
- 服務層
- 提供各類用戶使用接口 {select...}
- 提供SQL優化器
- 引擎層(提供了各類存儲的方式InnoDB MyISAM)
- 存儲層(存儲數據)數組
```sql
mysql> show engines; 查看支持那些引擎
```緩存
```sql
create table tb(
id int(4) auto_increment,
name varchar(5),
dept varchar(5),
primary key(id)
)ENGINE=MyISAM AUTO_INCREMENT=1
DEFAULT CHARSET=utf8
```服務器
## SQL優化數據結構
緣由:原始的sql語句可能性能低,執行時間太長,SQL語句欠佳,索引失效,服務器參數不合理(緩衝區,線程池)性能
SQL:學習
編寫過程。。。
解析過程 。。。
SQL優化主要是優化索引。索引(B樹, hash)
索引:幫助mysql高效得到數據的數據結構
索引弊端:
-索引的存儲空間比較大
-索引不是全部狀況適合,少許數據,頻繁更新不適合
-索引下降增刪改的效率
優點:提升查詢效率,下降IO,
CPU 使用率
索引分類:
單值索引:單值, age; 一個表能夠有多個單值索引
惟一索引:不能重複
符合索引:多個列組合的索引,至關於二級目錄。(name, age)
建立索引:
create 索引類型 索引名 on 表(字段)
語法
單值:
create index dept_index on tb(dept);
惟一索引:
create unique name_index on tb(name);
符合索引
create index dept_name__index on tb(dept, name);
alter table 表名 索引類型 索引名 類型
[alter table tb add index dept_index(dept)]
注意:若是一個字段是primary key,默認是主鍵索引。
刪除索引
drop index 索引名 on 表名
查詢索引
show index from 表名
---
研究sql性能問題
a, 分析sql的執行計劃: explain,模擬SQL優化器執行SQL優化器
b,Mysql優化器干擾咱們的優化
查看測試優化結果
```sql
mysql> explain select * from tb \G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: tb
type: system
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 0
Extra: const row not found
1 row in set (0.00 sec)
```
ps:explain能夠查看sql優化的結果,'\G', 或者 ' ; ' 會在選擇上不一樣
id 越大越優先,相等從上到下
type: system>const>eq_ref>ref>range>index>all
效率,越左邊越快,優化的前提必須有索引
system:只有一條數據的系統表,只有一條查詢;或衍生表只有一條數據的主查詢
const:僅僅能查到一條數據的SQL用於primary key或unique
以上部分咱們對數據庫優化有了一個初步瞭解
下面的部分知識是基於《高性能Mysql》和《Mysql技術內幕》的
## Schema 與數據類型優化
參考《高性能Mysql》
- 儘量使用正確的最小數據類型
- 最小夠用,可是要避免不足而帶來的數據類型範圍修改操做,存儲空間內存緩存消耗相對少
- 簡單就好
- 簡單數據類型的規則耗費更小的CPU週期,例如整數比字符串代價更低。字符集涉及校對規則。所以儘量用Mysql日期類型,而非字符串
- 儘可能避免NULL
- NULL對於SQL語句優化更困難。
**Mysql schema設計中的陷阱**
ps: schema是設計,概述,表結構的意思,書籍原標題是這樣的
- 太多的列很差
- mysql存儲引擎工做的時候在服務層和存儲引擎之間經過行緩衝格式拷貝數據,而後在服務層將緩衝內容解碼成各個列。從行緩衝中將解碼過的列轉成行數據結構的代價比較大。
- 太多的關聯
- 這裏書中批判「實體-屬性-值」設計模式很糟糕,在Mysql中會對於優化形成壓力。Mysql限制每一個關聯操做最大隻能有61張表。
**範式和反範式**
數據庫中咱們用第X範式來描述一個數據庫表的設計,越高意味着冗餘越低。維護代價也更高。可是必定的冗餘也並不是毫無優勢。也許能更有利於SQL優化引擎。
**Alter table**
alter修改表結構,底層的一種策略是使用複製表的方式修改(不是全部alter引發表的重建)。消耗比較大,並且鎖表。容易影響服務器的性能,一種方式是用基於插件,或者其餘服務,在其餘服務器上alter table然後拷貝,同步。
書中介紹了一些非官方的優化技巧,須要承擔一點分析這裏不提。
## 高性能索引
ps:這不是一篇科普性文章,只是個人學習筆記,因此不會全面解釋索引的優勢。
- 索引並不是老是好的
想起以前的一個例子。對於一個數組,找到一個數字,最好的方法是什麼。有些會想起無數數據結構。
可是!!!
若是隻須要一次查詢遍歷便可。
數據結構的應用必定是結合具體需求的
當數據量小的時候,直接拿到內存中遍歷效率和不斷在索引樹上IO到是真不必定那個更好。
下面的sql語句就沒法使用索引優化查詢。mysql沒法解析這個行爲
```sql
select actor_id from actor where actor_id + 1 = 5;
```
因此咱們儘可能把索引列放到一側。
```sql
select actor_id from actor where actor_id = 4;
```
- 爲全部的where後面的內容都加上索引?
若是多個索引作or, and 操做,維護索引會耗費大量內存,早期版本中鼓勵用語句的嵌套,而非or, and帶索引的列。這樣效率不必定更優於直接查。
- select * ???
所有取出來會讓優化器沒法完成索引覆蓋掃描這類優化。除非一些緩存技術的須要,不然不用這樣用。
- 優化查詢次數
例如用戶屢次須要查看某個東西各自的URL,每次都單獨調用URL是很差的,儘可能使用緩存的設計。
。。。
。。。
。。。
總結:sql優化主要集中在如何高效的使用索引上
## sql執行過程
- 客戶端 通過客戶端與服務器的通訊協議到達 Mysql服務器(半雙工)- 服務器先查詢緩存,查到返回,不然下一步- 解析SQL,預處理,由優化器生成對應的執行計劃。- MySQL根據優化器生成執行計劃,調用存儲引擎API執行查詢- 將結果返回客戶端