知识点:Mysql 数据库索引优化实战(4)
?
知識(shí)點(diǎn):Mysql 索引原理完全手冊(cè)(1)
知識(shí)點(diǎn):Mysql 索引原理完全手冊(cè)(2)
知識(shí)點(diǎn):Mysql 索引優(yōu)化實(shí)戰(zhàn)(3)
知識(shí)點(diǎn):Mysql 數(shù)據(jù)庫(kù)索引優(yōu)化實(shí)戰(zhàn)(4)
一:插入訂單
業(yè)務(wù)邏輯:插入訂單數(shù)據(jù),為了避免重復(fù)導(dǎo)單,一般會(huì)通過(guò)交易號(hào)去數(shù)據(jù)庫(kù)中查詢,判斷該訂單是否已經(jīng)存在。
最基礎(chǔ)的sql語(yǔ)句
mysql> select * from book_order where order_id = "10000"; +-------+--------------------+-------+------+----------+--------------+----------+------------------+-------------+-------------+------------+---------------------+ | id | order_id | general | net | stock_id | order_status | description | finance_desc | create_type | order_state | creator | create_time | +-------+--------------------+-------+------+----------+--------------+----------+------------------+-------------+-------------+------------+---------------------+ | 10000 | 10000 | 6.6 | 6.13 | 1 | 10 | ok | ok | auto | 1 | itdragon | 2018-06-18 17:01:52 | +-------+--------------------+-------+------+----------+--------------+----------+------------------+-------------+-------------+------------+---------------------+ mysql> explain select * from book_order where order_id = "10000"; +----+-------------+---------------------+------------+------+---------------+------+---------+------+------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+---------------------+------------+------+---------------+------+---------+------+------+----------+-------------+ | 1 | SIMPLE | book_order | NULL | ALL | NULL | NULL | NULL | NULL | 3 | 33.33 | Using where | +----+-------------+---------------------+------------+------+---------------+------+---------+------+------+----------+-------------+幾百上千萬(wàn)的訂單,全表掃描!
通過(guò)explain命令可以清楚MySQL是如何處理sql語(yǔ)句的。打印的內(nèi)容分別表示:
- id : 查詢序列號(hào)為1。
- select_type : 查詢類(lèi)型是簡(jiǎn)單查詢,簡(jiǎn)單的select語(yǔ)句沒(méi)有union和子查詢。
- table : 表是 book_order。
- partitions : 沒(méi)有分區(qū)。
- type : 連接類(lèi)型,all表示采用全表掃描的方式。
- possible_keys : 可能用到索引為null。
- key : 實(shí)際用到索引是null。
- key_len : 索引長(zhǎng)度當(dāng)然也是null。
- ref : 沒(méi)有哪個(gè)列或者參數(shù)和key一起被使用。
- Extra : 使用了where查詢。
是type為ALL,全表掃描,假設(shè)數(shù)據(jù)庫(kù)中有幾百萬(wàn)條數(shù)據(jù),在沒(méi)有索引的幫助下會(huì)異常卡頓。
初步優(yōu)化:為order_id創(chuàng)建索引
mysql> create unique index idx_order_transaID on book_order (order_id); mysql> explain select * from book_order where order_id = "10000"; +----+-------------+---------------------+------------+-------+--------------------+--------------------+---------+-------+------+----------+-------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+---------------------+------------+-------+--------------------+--------------------+---------+-------+------+----------+-------+ | 1 | SIMPLE | book_order | NULL | const | idx_order_transaID | idx_order_transaID | 453 | const | 1 | 100 | NULL | +----+-------------+---------------------+------------+-------+--------------------+--------------------+---------+-------+------+----------+-------+這里創(chuàng)建的索引是唯一索引,而非普通索引。
唯一索引打印的type值是const。表示通過(guò)索引一次就可以找到。即找到值就結(jié)束掃描返回查詢結(jié)果。
普通索引打印的type值是ref。表示非唯一性索引掃描。找到值還要繼續(xù)掃描,直到將索引文件掃描完為止。(這里沒(méi)有貼出代碼),顯而易見(jiàn),const的性能要遠(yuǎn)高于ref。并且根據(jù)業(yè)務(wù)邏輯來(lái)判斷,創(chuàng)建唯一索引是合情合理的。
再次優(yōu)化:覆蓋索引
mysql> explain select order_id from book_order where order_id = "10000"; +----+-------------+---------------------+------------+-------+--------------------+--------------------+---------+-------+------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+---------------------+------------+-------+--------------------+--------------------+---------+-------+------+----------+-------------+ | 1 | SIMPLE | book_order | NULL | const | idx_order_transaID | idx_order_transaID | 453 | const | 1 | 100 | Using index | +----+-------------+---------------------+------------+-------+--------------------+--------------------+---------+-------+------+----------+-------------+這里將select * from改為了select order_id from后,Extra 顯示 Using index,表示該查詢使用了覆蓋索引,說(shuō)明該sql語(yǔ)句的性能很好。若提示的是Using filesort(使用內(nèi)部排序)和Using temporary(使用臨時(shí)表)則表明該sql需要立即優(yōu)化了。
根據(jù)業(yè)務(wù)邏輯來(lái)的,查詢結(jié)構(gòu)返回order_id 是可以滿足業(yè)務(wù)邏輯要求的。
二:查詢訂單
業(yè)務(wù)邏輯:優(yōu)先處理訂單級(jí)別高,錄入時(shí)間長(zhǎng)的訂單。
通過(guò)訂單級(jí)別和訂單錄入時(shí)間排序
最基礎(chǔ)的sql語(yǔ)句
mysql> explain select * from book_order order by order_state,create_time; +----+-------------+---------------------+------------+------+---------------+------+---------+------+------+----------+----------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+---------------------+------------+------+---------------+------+---------+------+------+----------+----------------+ | 1 | SIMPLE | book_order | NULL | ALL | NULL | NULL | NULL | NULL | 3 | 100 | Using filesort | +----+-------------+---------------------+------------+------+---------------+------+---------+------+------+----------+----------------+首先,采用全表掃描就不合理,還使用了文件排序Using filesort,更加拖慢了性能。 MySQL在4.1版本之前文件排序是采用雙路排序的算法,由于兩次掃描磁盤(pán),I/O耗時(shí)太長(zhǎng)。后優(yōu)化成單路排序算法。其本質(zhì)就是用空間換時(shí)間,但如果數(shù)據(jù)量太大,buffer的空間不足,會(huì)導(dǎo)致多次I/O的情況。其效果反而更差。與其找運(yùn)維同事修改MySQL配置,還不如自己乖乖地建索引。
初步優(yōu)化:為order_state,create_time 創(chuàng)建復(fù)合索引
mysql> create index idx_order_stateDate on book_order (order_state,create_time); mysql> explain select * from book_order order by order_state,create_time; +----+-------------+---------------------+------------+------+---------------+------+---------+------+------+----------+----------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+---------------------+------------+------+---------------+------+---------+------+------+----------+----------------+ | 1 | SIMPLE | book_order | NULL | ALL | NULL | NULL | NULL | NULL | 3 | 100 | Using filesort | +----+-------------+---------------------+------------+------+---------------+------+---------+------+------+----------+----------------+創(chuàng)建復(fù)合索引后你會(huì)驚奇的發(fā)現(xiàn),和沒(méi)創(chuàng)建索引一樣???都是全表掃描,都用到了文件排序。是索引失效?還是索引創(chuàng)建失敗?
我們?cè)囍纯聪旅娲蛴∏闆r
mysql> explain select order_state,create_time from book_order order by order_state,create_time; +----+-------------+---------------------+------------+-------+---------------+---------------------+---------+------+------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+---------------------+------------+-------+---------------+---------------------+---------+------+------+----------+-------------+ | 1 | SIMPLE | book_order | NULL | index | NULL | idx_order_stateDate | 68 | NULL | 3 | 100 | Using index | +----+-------------+---------------------+------------+-------+---------------+---------------------+---------+------+------+----------+-------------+將select * from 換成了 select order_state,create_time from 后。type從all升級(jí)為index,表示(full index scan)全索引文件掃描,Extra也顯示使用了覆蓋索引??墒遣粚?duì)啊!!!!檢索雖然快了,但返回的內(nèi)容只有order_state和create_time 兩個(gè)字段,讓業(yè)務(wù)同事怎么用?難道把每個(gè)字段都建一個(gè)復(fù)合索引?
MySQL沒(méi)有這么笨,可以使用force index 強(qiáng)制指定索引。在原來(lái)的sql語(yǔ)句上修改 force index(idx_order_stateDate) 即可。
mysql> explain select * from book_order force index(idx_order_stateDate) order by order_state,create_time; +----+-------------+---------------------+------------+-------+---------------+---------------------+---------+------+------+----------+-------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+---------------------+------------+-------+---------------+---------------------+---------+------+------+----------+-------+ | 1 | SIMPLE | book_order | NULL | index | NULL | idx_order_stateDate | 68 | NULL | 3 | 100 | NULL | +----+-------------+---------------------+------------+-------+---------------+---------------------+---------+------+------+----------+-------+再次優(yōu)化:訂單級(jí)別真的要排序么?
對(duì)于這種重復(fù)且分布平均的字段,排序和加索引的作用不大。
我們能否先固定 order_state 的值,然后再給 create_time 排序?
mysql> explain select * from book_order where order_state=3 order by create_time; +----+-------------+---------------------+------------+------+---------------------+---------------------+---------+-------+------+----------+-----------------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+---------------------+------------+------+---------------------+---------------------+---------+-------+------+----------+-----------------------+ | 1 | SIMPLE | book_order | NULL | ref | idx_order_stateDate | idx_order_stateDate | 5 | const | 1 | 100 | Using index condition | +----+-------------+---------------------+------------+------+---------------------+---------------------+---------+-------+------+----------+-----------------------+和之前的sql比起來(lái),type從index 升級(jí)為 ref(非唯一性索引掃描)。索引的長(zhǎng)度從68變成了5,說(shuō)明只用了一個(gè)索引。ref也是一個(gè)常量。Extra 為Using index condition 表示自動(dòng)根據(jù)臨界值,選擇索引掃描還是全表掃描。總的來(lái)說(shuō)性能遠(yuǎn)勝于之前的sql。
小結(jié)
建索引:
- 主鍵,唯一索引
- 經(jīng)常用作查詢條件的字段需要?jiǎng)?chuàng)建索引
- 經(jīng)常需要排序、分組和統(tǒng)計(jì)的字段需要建立索引
- 查詢中與其他表關(guān)聯(lián)的字段,外鍵關(guān)系建立索引
不要建索引:
- 百萬(wàn)級(jí)以下的數(shù)據(jù)不需要?jiǎng)?chuàng)建索引
- 經(jīng)常增刪改的表不需要?jiǎng)?chuàng)建索引
- 數(shù)據(jù)重復(fù)且分布平均的字段不需要?jiǎng)?chuàng)建索引
- 頻發(fā)更新的字段不適合創(chuàng)建索引
- where條件里用不到的字段不需要?jiǎng)?chuàng)建索引
talk is esay , show me the code
轉(zhuǎn)載于:https://www.cnblogs.com/yizhiamumu/p/9226142.html
總結(jié)
以上是生活随笔為你收集整理的知识点:Mysql 数据库索引优化实战(4)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 中科大 EPC课程 爬虫(最新,效果良好
- 下一篇: mysql 5.6.38 数据库编译安装