學習筆記-數據庫優化

騰訊課堂,燕十八Mysql高性能優化https://ke.qq.com/course/171224

建表原則

  1. 變長字段和定長字段分離
  2. 常用字段和不常用字段分離
  3. 在1對多,需要關聯統計的字段上,添加冗余字段以減少查詢的壓力,寫入的時候麻煩一點

列類型選擇

  1. 字段類型優先級 整型>date,time>enum,char>varcahr>blob,text
  2. 性別:utf8為例
  3. char(1)三個字節
  4. enum('男','女')內部轉成數字來存,多了一個轉換過程
  5. tinyint(),0,1,2 定長1字節
  6. 夠用就行,不要慷慨
  7. 年齡:用 tinyint unsigned not null足夠,可以存0-255
  8. varchar(10),varcahr(300)存儲內容相同,但是在聯查時,后者占用更多內存
  9. 盡量避免使用null()

索引類型

  1. btree索引
  2. 將節點用樹進行索引
F18AEF581E92509B292295258BE85331.png
  1. 找到索引,再找到對應記錄的位置獲取詳情
  2. 提高排序/分組/查詢速度
  3. 誤區:
  4. where id>3 and price>100,那么在id和price都建立索引.這是錯誤的,因為索引是獨立的,這條語句只能用一個索引
  5. 聯合索引:左前綴索引,按索引順序(語句可替換) 使用索引
  6. hash索引
  7. 將索引hash,放入對應位置
  8. 范圍查找,不好使
  9. 排序無法優化
  10. 優點,復雜度理論為O(1)
  11. 非聚簇索引
  12. myisam:索引和數據是分開的
  13. 回行拿數據
    4.聚簇索引
  14. innoDB:索引和數據是放在一起的
  15. 主鍵索引即存儲索引,又存儲數據
  16. 非主鍵索引的數據指向主鍵鍵索引:即先找到name,name節點存儲了id,再到id索引找到詳細數據

修復表

  1. 索引碎片與維護
  2. 在長期的數據更改過程中,索引文件和數據文件,都將產生空洞,形成碎片
  3. 可以通過Nop(不產生對數據實質影響的操作)來修復表:
  4. alter table xxx engine innodb;本來就是innodb引擎
  5. optimize table name 來修復表
  6. 把數據文件對齊,比較耗資源,不能頻繁操作,如果update 操作頻繁周/月 來修復,不頻繁則更長周期來修復

explain

字段 解釋
id: 該語句中查詢語句的id(因為可能是嵌套查詢)
select_type: 見下圖
table : 查詢的表\別名
possible_keys: 可能用到的key
key: 用到的key
type: 查詢的方式,非常重要,是分析"查數據過程"all/index/range/ref/const/system/null效果越來越好
ref: 連接查詢是,表字段的引用關系
rows: 估計要掃描的行數
extra: 1. index:用到了索引覆蓋,效率非常高;2. usering where指光靠索引不能定位,還要where判斷一下;3. usering temporary用了臨時表,group by 與order by 不同列時,或group by order by別的表的列;4. usering filesort:文件排序
0350565611272DB6AB52F0DA38415432.png

in型子查詢陷阱

mysql的查詢優化器,針對in型查詢做了優化,被改成了exists子茶行的執行效果
改進:用鏈接查詢代替子查詢

count小技巧

表a有44555550條數據
想知道id大于1000的有多少條數據
直接select count() from a where id>1000;耗時可能有4/5s
優化策略:
select count(
) from a 得到總記錄數 total;
select count(*) from a<=1000得到記錄數 lt1000;
total-lt1000=總數-一小塊=剩下一大塊

union小技巧

union會排序,去重
union all 不會排序去重

limit翻頁優化

limit隨著翻頁offset的增長,越來越慢
limit 10000,5 :拿出10005行,丟掉前邊10000行,返回5行數據

改進方法
用where進行優化
select * from a where id>10000 limit 5;
這個要求數據id不能斷

思路是:將分頁只在索引葉子上進行,得到要獲取的id,然后根據id區查詢詳情:
select * from a inner join (select id from a limit 1000000,5) as b on a.id=b.id;

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容