Python- 索引 B+數 好比書的目錄

1.索引
爲什麼要有索引?
通常的應用系統,讀寫比例在10:1左右,並且插入操做和通常的更新操做不多出現性能問題,
在生產環境中,咱們遇到最多的,也是最容易出問題的,仍是一些複雜的查詢操做,
所以對查詢語句的優化顯然是重中之重。提及加速查詢,就不得不提到索引了。

彙集索引
葉子節點整個行中的額數據
輔助索引
葉子節點存儲的是索引字段 和主鍵值
覆蓋索引
回表
聯合索引

正確使用索引
1.區分度高字段
2.索引的字段數據量應該儘量小
3.優先使用匯集索引
4.聯合索引 建立時 把區分度高放左邊
查詢時 儘量使用最左邊的索引

索引越多越好?
索引可以提高效率
同時下降了寫入速度
增長額外的磁盤佔用

2.元類
用於建立類的類 叫元類 默認元類都是type
主要控制類的建立__init__ 類的實例化__call__

3.單例
一個類只有一個實例
何時用,你們公用一個打印機,沒有必要每一個人建立新的打印機對象 共用一個對象便可


應該被索引的字段

須要排序操做的字段(order_by)
須要比較操做的字段(> < >= <=)
須要過濾操做的字段( filter exclude)python

不該該索引的字段

常常更新和刪除 的字段不該該被索引mysql

默認索引的規則

主鍵一定是索引sql

外鍵 默認是索引 (能夠不配置)數據庫

添加索引的方法:

屬性中定義
meta中定義django

from django.db import models
from apis.models import App

# Create your models here.
class User(models.Model):
    # open_id
    open_id = models.CharField(max_length=64, unique=True)
    # 暱稱
    nickname = models.CharField(max_length=256, db_index=True)
    # 關注的城市
    focus_cities = models.TextField(default='[]')
    # 關注的星座
    focus_constellations = models.TextField(default='[]')
    # 關注的股票
    focus_stocks = models.TextField(default='[]')

    # 菜單app
    menu = models.ManyToManyField(App)
  
    class Meta:
        indexes = [
            # models.Index(fields=['nickname'])
            models.Index(fields=['open_id', 'nickname'])
        ]

    def __str__(self):
        return self.nickname

    def __repr__(self):
        return self.nickname

  

===============================索引01 爲何要用索引    由於項目運行中,查詢操做很是頻繁,爲了提升用戶體驗,要提升查詢的速度,    如何提升就靠索引(大多數性能問題都是慢查詢  提到加速查,就必須用到索引)    做用:        - 約束        - 加速查找02 什麼是索引    搜索引導, 因此是一種單獨的,物理的 有序的 存儲結構,用於加速查詢        例如: 字典  書的目錄  車票上的車箱號    索引的本質原理就是經過不斷地縮小查詢範圍,來下降io次數從而提高查詢性能    強調:一旦爲表建立了索引,之後的查詢都會先查索引,再根據索引定位的結果去找數據本質都是:經過不斷地縮小想要獲取數據的範圍來篩選出最終想要的結果,同時把隨機的事件變成順序的事件,        也就是說,有了這種索引機制,咱們能夠老是用同一種查找方式來鎖定數據。03 索引的影響    1.加速查詢    2.下降寫入(增長 刪除 修改)速度    3.會額外佔用磁盤空間4.索引的分類    1.彙集索引 就是主鍵索引 (primary key )        - 主鍵索引:加速查找 + 不能爲空 + 不能重複        行中的完整記錄存在彙集索引的葉子節點上    2.輔助索引  (unique,index)        - 普通索引:加速查找        - 惟一索引:加速查找 + 不能重複        葉子節點 存儲索引字段的值 還有 主鍵的值        使用輔助索引時 會產生兩種現象        1.回表    要查的數據就不在輔助索引中 須要到彙集索引中查找        2.覆蓋索引  要查的數據就在輔助索引中        - create index 索引名稱 on 表名(列名,)        - drop index 索引名稱 on 表名        - create unique index 索引名稱 on 表名(列名)        - drop unique index 索引名稱 on 表名    3 聯合索引(多列):            - 聯合主鍵索引            - 聯合惟一索引            - 聯合普通索引        爲是什麼使用它        下降資源的佔用 , 下降增刪改的時間   會比單個字段的索引快        創建聯合索引時 應該把區分度高放最左邊  區分度低的依次往右放        按照區分度的高低 從左往右  依次排列        查詢中 應該優先使用左邊的索引        使用and時 無所謂書寫順序 會自動找區分度最高的        注意聯合索引在查詢時  若是壓根沒用到最左側索引 不能加速查詢        組合索引(最左前綴匹配):        - create unique index 索引名稱 on 表名(列名,列名)        - drop unique index 索引名稱 on 表名        - create index ix_name_email on userinfo3(name,email,)        - 最左前綴匹配                select  * from userinfo3 where name='alex';                select  * from userinfo3 where name='alex' and email='asdf';                select  * from userinfo3 where email='alex@qq.com';        組合索引效率 > 索引合併            組合索引                - (name,email,)                    select  * from userinfo3 where name='alex' and email='asdf';                    select  * from userinfo3 where name='alex';            索引合併:                - name                - email                    select  * from userinfo3 where name='alex' and email='asdf';                    select  * from userinfo3 where name='alex';                    select  * from userinfo3 where email='alex';        名詞:            覆蓋索引:                - 在索引文件中直接獲取數據            索引合併:                - 把多個單列索引合併使用索引的正確使用姿式    命中索引 ,條件中有索引字段匹配上    1.不管索引如何設計 沒法下降範圍查詢的查詢速度        select count(*) from usr where id > 1;        即便命中索引也沒法提升效率    2.索引不該該加在值重複度很高的字段上 應該加在重複度低的字段    3. 使用and時 當 條件中出現多個索引命中時  會自定找一個區分度最高的索引來使用    4.使用or的時候  若是兩邊都有索引 會使用索引,可是注意 or兩邊都要執行  順序依然從左往右    只有一邊有索引會不會使用索引?  不會使用 沒法加速查詢    5.優化查詢 不只僅要加索引,sql語句也須要優化 使其能命中索引            你的條件中應該使用區別度高的索引    正常開發時    優先使用匯集索引    再次 使用聯合索引  若是你的條件不包含最左側索引  不能加速查詢 這時候就應該使用單個字段索引    建立索引:        create index 索引名稱 on usr(索引字段);索引未命中  詳見49-2並非說咱們建立了索引就必定會加快查詢速度,若想利用索引達到預想的提升查詢速度的效果,咱們在添加索引時,必須遵循如下問題1 範圍問題,或者說條件不明確,條件中出現這些符號或關鍵字:    >、>=、<、<=、!= 、between...and...、like、        大於號、小於號        不等於!=        between ...and...        like2 儘可能選擇區分度高的列做爲索引,區分度的公式是count(distinct col)/count(*),    表示字段不重複的比例,比例越大咱們掃描的記錄數越少,惟一鍵的區分度是1,    而一些狀態、性別字段可能在大數據面前區分度就是0,那可能有人會問,    這個比例有什麼經驗值嗎?使用場景不一樣,這個值也很難肯定,    通常須要join的字段咱們都要求是0.1以上,即平均1條掃描10條記錄3 =和in能夠亂序,好比a = 1 and b = 2 and c = 3 創建(a,b,c)索引能夠任意順序,    mysql的查詢優化器會幫你優化成索引能夠識別的形式4 索引列不能參與計算,保持列「乾淨」,好比from_unixtime(create_time) = ’2014-05-29’就不能使用到索引,    緣由很簡單,b+樹中存的都是數據表中的字段值,但進行檢索時,須要把全部元素都應用函數才能比較,    顯然成本太大。因此語句應該寫成create_time = unix_timestamp(’2014-05-29’)5 and/or6 最左前綴匹配原則(詳見第八小節),很是重要的原則,對於組合索引mysql會一直    向右匹配直到遇到範圍查詢(>、<、between、like)就中止匹配(指的是範圍大了,有索引速度也慢),    好比a = 1 and b = 2 and c > 3 and d = 4 若是創建(a,b,c,d)順序的索引,    d是用不到索引的,若是創建(a,b,d,c)的索引則均可以用到,a,b,d的順序能夠任意調整。7 其餘狀況總結    #1. 必定是爲搜索條件的字段建立索引,好比select * from s1 where id = 333;就須要爲id加上索引    #2. 在表中已經有大量數據的狀況下,建索引會很慢,且佔用硬盤空間,建完後查詢速度加快        好比create index idx on s1(id);會掃描表中全部的數據,        而後以id爲數據項,建立索引結構,存放於硬盤的表中。建完之後,再查詢就會很快了。    #3. 須要注意的是:innodb表的索引會存放於s1.ibd文件中,而myisam表的索引則會有單獨的索引文件table1.MYI    MySAM索引文件和數據文件是分離的,索引文件僅保存數據記錄的地址。    而在innodb中,表數據文件自己就是按照B+Tree(BTree即Balance True)組織的一個索引結構,    這棵樹的葉節點data域保存了完整的數據記錄。這個索引的key是數據表的主鍵,所以innodb表數據文件自己就是主索引。    由於inndob的數據文件要按照主鍵彙集,因此innodb要求表必需要有主鍵(Myisam能夠沒有),    若是沒有顯式定義,則mysql系統會自動選擇一個能夠惟一標識數據記錄的列做爲主鍵,    若是不存在這種列,則mysql會自動爲innodb表生成一個隱含字段做爲主鍵,這字段的長度爲6個字節,類型爲長整型.-----wusir2. 頻繁查找的列建立索引    - 建立索引    - 命中索引 *****        - like '%xx'            select * from tb1 where email like '%cn';        - 使用函數            select * from tb1 where reverse(email) = 'wupeiqi';        - or            select * from tb1 where nid = 1 or name = 'seven@live.com';            特別的:當or條件中有未創建索引的列才失效,如下會走索引                    select * from tb1 where nid = 1 or name = 'seven';                    select * from tb1 where nid = 1 or name = 'seven@live.com' and email = 'alex'        - 類型不一致            若是列是字符串類型,傳入條件是必須用引號引發來,否則...            select * from tb1 where email = 999;        - !=            select * from tb1 where email != 'alex'            特別的:若是是主鍵,則仍是會走索引                select * from tb1 where nid != 123        - >            select * from tb1 where email > 'alex'            特別的:若是是主鍵或索引是整數類型,則仍是會走索引                select * from tb1 where nid > 123                select * from tb1 where num > 123        - order by            select name from tb1 order by email desc;            當根據索引排序時候,選擇的映射若是不是索引,則不走索引            特別的:若是對主鍵排序,則仍是走索引:                select * from tb1 order by nid desc;        - 組合索引最左前綴            若是組合索引爲:(name,email)            name and email       -- 使用索引            name                 -- 使用索引            email                -- 不使用索引3. 查詢優化神器-explain    關於explain命令相信你們並不陌生,具體用法和字段含義能夠參考官網explain-output,    這裏須要強調rows是核心指標,絕大部分rows小的語句執行必定很快    (有例外,下面會講到)。因此優化語句基本上都是在優化rows。   執行計劃:讓mysql預估執行操做(通常正確)        all < index < range < index_merge < ref_or_null < ref < eq_ref < system/const        id,email        慢:            select * from userinfo3 where name='alex'            explain select * from userinfo3 where name='alex'            type: ALL(全表掃描)                select * from userinfo3 limit 1;        快:            select * from userinfo3 where email='alex'            type: const(走索引)4. DBA工做    慢查詢優化的基本步驟        0.先運行看看是否真的很慢,注意設置SQL_NO_CACHE        1.where條件單表查,鎖定最小返回記錄表。這句話的意思是把查詢語句的where都應用到表中返回的記錄數最小的表開始查起,單表每一個字段分別查詢,看哪一個字段的區分度最高        2.explain查看執行計劃,是否與1預期一致(從鎖定記錄較少的表開始查詢)        3.order by limit 形式的sql語句讓排序的表優先查        4.瞭解業務方使用場景        5.加索引時參照建索引的幾大原則        6.觀察結果,不符合預期繼續從0分析    慢日誌        - 執行時間 > 10        - 未命中索引        - 日誌文件路徑    配置:        - 內存            show variables like '%query%'            set global 變量名 = 值        - 配置文件            mysqld --defaults-file='E:\wupeiqi\mysql-5.7.16-winx64\mysql-5.7.16-winx64\my-default.ini'            my.conf內容:                slow_query_log = ON                slow_query_log_file = D:/....            注意:修改配置文件以後,須要重啓服務5. ******分頁*******    a. select * from userinfo3 limit 20,10;    b.        - 不讓看        - 索引表中掃:            select * from userinfo3 where id in(select id from userinfo3 limit 200000,10)        - 方案:            記錄當前頁最大或最小ID            1. 頁面只有上一頁,下一頁                # max_id                # min_id                下一頁:                    select * from userinfo3 where id > max_id limit 10;                上一頁:                    select * from userinfo3 where id < min_id order by id desc limit 10;            2. 上一頁 192 193  [196]  197  198  199 下一頁                select * from userinfo3 where id in (                    select id from (select id from userinfo3 where id > max_id limit 30) as N order by N.id desc limit 10                )    c. *****閆龍*****:        id不連續,因此沒法直接使用id範圍進行查找1. ORM框架:SQLAlchemy    SQLAlchemy是Python編程語言下的一款ORM框架,該框架創建在數據庫API之上,使用關係對象映射進行數據庫操做,    簡言之即是:將對象轉換成SQL,而後使用數據API執行SQL並獲取執行結果。      - 做用:         1. 提供簡單的規則         2. 自動轉換成SQL語句      - DB first: 手動建立數據庫以及表          -> ORM框架 -> 自動生成類      - code first: 手動建立類、和數據庫        -> ORM框架 -> 以及表      a. 功能         - 建立數據庫表            - 鏈接數據庫(非SQLAlchemy,pymyql,mysqldb,....)            - 類轉換SQL語句         - 操做數據行            增            刪            改            查         - 便利的功能
相關文章
相關標籤/搜索