1. 程式人生 > >資料庫優化一般思路(個人經驗之談)

資料庫優化一般思路(個人經驗之談)

  隨著系統規模的不斷增加,資料量和併發量不斷增大,整個系統架構中最先受到衝擊而形成瓶頸的,定然是資料庫,因此資料庫層面的優化,是一個程式設計師不可或缺的技能,以下是我在使用資料庫中的一些心得,有不足之處,還望批評指正完善。

        首先簡單介紹下sql執行的過程,如下圖

        

      當你在sql客戶端(如命令列或者navicat)提交一條sql後,sql解析引擎會被啟動,此時,sql引擎會去解析優化這條sql,比如有時候你發現你寫的sql 查詢條件中的資料型別雖然和資料庫表定義的資料型別不一致,但是還是能夠得到正確的執         行,是因為資料庫引擎幫你做了自動轉化,比如

       select * from user where telephone=13937147647   telephone為varchar型別

        雖然型別不一致,但是sql會得到正確執行,是因為資料庫引擎幫你做了自動型別轉化

        不僅如此,資料庫表定義了多個索引,你寫的sql可能都會命中,sql引擎會幫你選擇最優的一個,這些都是此階段完成的 

        接下來,資料庫引擎會拿著優化好的sql命令語義去硬碟中查詢資料,然後將查詢到的資料返回(如果此時返回的結果集過大,會造成資料庫IO繁忙,會大大損傷sql效率,所以一般我們都使用分頁的原因就在於此)

        我們熟悉了sql執行過程之後,開始瞭解各種優化方式吧:

        1、索引,建立索引是資料庫優化各種方案之中成本最低,見效最快的解決方案,一般來講,資料庫規模在幾十萬和幾百萬級別的時候見效最快,即便是有不太複雜的表關聯,也能大幅度提高sql的執行效率,這個在我們以前的專案應用中,有非常深刻的體會,本來耗時50s的sql,在增加索引後可以提升到1-2s,而且不需要有程式碼改動,成本低廉,見效明顯

         建立索引需要注意的地方

         a、索引一般加在查詢條件的關鍵字上,如果有多個查詢條件關鍵字,還可以新增組合索引,寫sql的時候需要注意,索引欄位和sql欄位需要保持一致,否則索引會無效

,比如

              簡單粗暴一點兒,我直接使用我們主資料資料庫(測試庫)中的md_house_property_info表中的source_house_code_no欄位,這個欄位在資料庫中被定義為了varchar型別,定義了多個索引,都包含了source_house_code_no欄位

             

           大家看,source_house_code_no我寫成varchar型別的時候,是可以走索引的

          

         當我寫成數字的時候,sql能夠正確執行,但是卻沒有命中索引

         大家再細心一點兒會發現,我這裡面有個possiable_keys,這個是指的可能命中的索引,此處出現了兩個,但是資料庫引擎會選擇最優的一個idx_source_house_code_no,這個過程我在開始有介紹了

        b、不要在查詢=前面使用函式,否則會導致索引不生效,舉個栗子,where str=substring(“hello world”,6,8),這樣是可以走索引的,但是 where substring(str,6,8)=“hello world” 是不會命中索引的

        c、建立索引的欄位要區分度比較高,比如user表中有一個性別字段,性別欄位無非男女兩種值,區分度不好,建立索引效果不好,要選擇區分度高的欄位

        d、建立組合索引,可以持續提升sql執行效率,但是也不要盲目,同樣的要注意區分度,如果區分度不夠高,就不要加了,多個欄位,儘可能把區分度高的欄位放在前面,另外,還要注意索引長度,這個索引要同時兼顧索引長度和區分度的平衡

        e、索引會大幅提升查詢效率,但是也會損耗查詢後修改效率,要注意兼顧平衡,使用在一次插入,多次查詢的表上效果最好,同時要注意的是,組合索引會不可避免的增加索引長度,會增加索引儲存空間,注意索引長度和區分度平衡

        f、後來因為工作需要,意外發現mysql居然支援全文索引,沒測試過效率,正常使用全文索引都是使用 lunce,以及在其之上的solr和現在正火的elastisearch,後面可以單獨來說

        2、分庫分表分割槽

        分庫,可以按照業務分庫,分流資料庫併發壓力,使資料庫表更加有條理性,最起碼更加好找吧,我們當時是把查詢庫和系統庫(增刪改比較頻繁的表)分開了,這樣如果有大查詢,不影響系統庫

        分表,剛才說了,索引適合應對百萬級別的資料量,千萬級別資料量使用的好,勉強也能湊合,但如果是上億級別的資料量,索引就無能為力了,因為單索引檔案可能就已經上百兆或者更多了,那麼,輪到我們的分表分割槽登場了

        分表的方法有很多種

        a、如果這個業務是有流程的,那麼我們通常會設計一個歷史表或者歸檔表,用來存放歷史資料,這樣能保證實時資料效率比較高

        b、針對某一張大表,可以根據查詢條件分成多張表,比如時間,我們可以將半個月或者10天的資料放到一張表裡(看具體資料量,個人認為3000W是個上限,最好控制到百萬級別),每過10天,我們就自動建立一張資料庫表,然後將資料插入,如此,按照時間查詢,就要先定位去那種表中去取數,這樣,效率能夠得到大幅度提升,當然,這麼解決也有問題,比如跨表,需要union多張表,而且跨表沒法支援索引

         c、上面的方法是我們直接通過程式和資料庫實現的最原始的分表解決方案,現在市面上有一些成熟的軟體如mycat,也是支援分表的,我們之前從事的公司有個專門做分散式資料庫的,這些產品出現跨表,可以不使用程式union了,而且還是使索引生效,但是需要對產品有一定的掌握

         d、一般來講,資料庫中的大表畢竟只是一少部分,僅需要對這少部分大表進行分表就可以了,沒必要小表也進行分表,增加維護開發難度

        分割槽

        分割槽的實現道理和分表一樣,也是將相應規則的資料放在一起,唯一不同的是分割槽你只需要設定好分割槽規則,插入的資料會被自動插入到指定的區裡,當然查詢的時候也能很快查詢到需要區,相當於是分表對外透明瞭,出現跨表資料庫自動幫我們合併做了處理,使用起來比分表更加方便,但是分割槽也有自己的問題,每一個數據庫表的併發訪問是有上限的,也就是說,分表能夠抗高併發,而分割槽不能,如何選擇,要考慮實際情況

       3、資料庫引擎

            也是偶爾聽一個dba同事提到的,有一次我跟dba同事抱怨,我的資料庫查詢太慢,有沒有好的優化方法,他一開始就問,資料量多大,有沒有索引,使用的什麼資料庫引擎,這時我才意識到原來資料庫引擎也算是一種優化方案

            mysql比較常用的資料庫引擎有兩種,一種是innodb、一種是myisam 

            我當時做過一個千萬級資料量複雜sql測試,myisam的效率大概能夠比innodb快1-2倍,雖然效率提升不是很明顯,但是也有提升,後來查過一些資料,說之所以mysiam快,是因為他的資料儲存結構、索引儲存結構和innodb不一樣的,mysiam的索引結構是在記憶體中存的

            當然,mysiam也有弱點,那就是他是表級鎖,而innodb是行級鎖,所以,mysiam適用於一次插入,多次查詢的表,或者是讀寫分離中的讀庫中的表,而對於修改插入刪除操作比較頻繁的表,就很不合適了

       4、預處理

        一般來說,實時資料(當天的資料)還是比較有限的,真正資料量比較大的是歷史資料,基於大表歷史資料的查詢,如果再涉及一些大表關聯,這種sql是非常難以優化的

       a、實時資料(當天資料)

            通過對對業務的抽象,可以放在快取裡面,提升系統執行效率

       b、歷史資料,大資料表歷史資料且有表關聯,通過常規sql難以優化,但是該資料通常有個共性,就是第二天去查詢前一天的資料做分析報表,也就是說對時效性要求不高,這種情況的解決方案是預處理

             做法是將這些複雜表關聯sql寫成個定時任務在半夜執行,將執行的結果存入到一張結果表中,第二天直接查詢結果表,如此,效率能得到十分明顯提升

       c、和b類似,可以將表關聯結果存入solr或者elastisearch中,以此提升效率,目前我們的專案就是如此處理

       5、mysql  like查詢

            大家都知道,like  “%str%” 不支援索引, "str%"號是支援索引的

            因此,如果業務允許,可以使用前匹配的方法是資料庫快速定位到資料,在結果集中再進行like匹配,如果這個結果集不是很大,是可以大幅提升執行效率的,這個需要對業務和程式有靈活的變通

            如果業務實在不允許前匹配,那就可以採用solr或者elastisearch來進行模糊匹配,但是進行模糊匹配有個前提,原始資料是字串的話,不要帶有特殊符號,如#,&,% 等,這樣會造成分詞不準,最終導致查詢結果不正確

      6、讀寫分離

           在資料庫併發大的情況下,最好的做法就是進行橫向擴充套件,增加機器,以提升抗併發能力,而且還兼有資料備份功能

相關推薦

資料庫優化一般思路(個人經驗之談)

  隨著系統規模的不斷增加,資料量和併發量不斷增大,整個系統架構中最先受到衝擊而形成瓶頸的,定然是資料庫,因此資料庫層面的優化,是一個程式設計師不可或缺的技能,以下是我在使用資料庫中的一些心得,有不足之處,還望批評指正完善。         首先簡單介紹下sql執行的過

資料庫優化一般思路

隨著系統規模的不斷增加,資料量和併發量不斷增大,整個系統架構中最先受到衝擊而形成瓶頸的,定然是資料庫,因此資料庫層面的優化,是一個程式設計師不可或缺的技能,以下是我在使用資料庫中的一些心得,有不足之處,還望批評指正完善。         首先簡單介紹下sql執行的過程,如下

面試求職:資料庫常見面試題(資料庫優化思路

查詢分析器中執行:--建表table1,table2:create table table1(id int,name varchar(10))create table table2(id int,score int)insert into table1 select 1,'lee'insert into ta

資料庫優化SQL

sql優化規則: 1.對於查詢,儘量不要使用全表掃描,儘量在where子句以及order by所對應的欄位建立索引。 2.應儘量避免在 where 子句中對欄位進行 null 值判斷,否則將導致引擎放棄使用索引而進行全表掃描。   最好不要給資料庫留NULL,儘可能的使用 NOT NULL填充

中小企業網站優化推廣思路方法技巧

如今很多中小企業都有自己的企業官網,其中絕大多數企業網站都沒有注意優化,今天小編簡單分享關於中小企業網站優化思路方向。 1、域名與主機選擇 企業站點域名建議選擇與品牌相關或者與主營相關,選擇.com .cn 等字尾域名都可以;關於空間選擇目前國內主機服務商很多都還不錯,如:阿里雲、

mysql資料庫優化大全

資料庫優化 sql語句優化  索引優化  加快取  讀寫分離  分割槽  分散式資料庫(垂直切分)  水平切分  MyISAM和InnoDB的區別:  1. InnoDB支援事務,MyISAM不支援,對於InnoDB

JAVA效能優化,架構師,分散式框架,高可用框架,微服務架構,資料庫優化

程式碼優化,一個很重要的課題。可能有些人覺得沒用,一些細小的地方有什麼好修改的,改與不改對於程式碼的執行效率有什麼影響呢?這個問題我是這麼考慮的,就像大海里面的鯨魚一樣,它吃一條小蝦米有用嗎?沒用,但是,吃的小蝦米一多之後,鯨魚就被餵飽了。 程式碼優化也是一樣,如果專案著眼於儘快無BUG上線,那麼此時可以抓

mysql資料庫優化(四)-專案實戰

在flask專案中,防止隨著時間的流逝,資料庫資料越來越多,導致介面訪問資料庫速度變慢。所以自己填充資料進行測試及 mysql優化 1.插入資料: 通過指令碼,使用多程序,每100次提交資料 import multiprocessing import time from fla

資料庫優化查詢方法總結

處理百萬級以上的資料提高查詢速度的方法: 1.應儘量避免在 where 子句中使用!=或<>操作符,否則將引擎放棄使用索引而進行全表掃描。 2.對查詢進行優化,應儘量避免全表掃描,首先應考慮在 where 及 order_by 涉及的列上建立索引。 3.應儘量避免在 wh

mysql資料庫優化小結

一、常見資料庫的優化操作 1、表的設計要符合三正規化。 2、新增適當的索引,索引對查詢速度影響很大,必須新增索引。主鍵索引,唯一索引,普通索引,全文索引 3、新增適當儲存過程,觸發器,事務等。 4、讀寫分離(主從資料庫) 5、對sql語句的一些優化,(查詢執行速度比較慢的sql語

關於資料庫優化的一些想法

優化table結構 #1 列資料型別儘量使用數字型別,避免使用字元型別,後者不僅會佔用較多儲存空間而且會降低查詢效率(逐字元比較); #2 優先使用VARCHAR,變長欄位儲存空間小,還可以提升查詢效率; #3 對需要經常作為where條件出現的column新增索引,通過新增constraint設定為u

Django - ORM 資料庫優化

目錄 一、defer 、only 查詢優化 二、事務 transaction - 原子性操作 三、choice -- 簡化不常變化的欄位 - 模型層內建立方式 - 檢視層 使用方式:物件(單).get_欄位名_display() author.get_dd_displa

大資料量高併發的資料庫優化詳解(MSSQL)

轉載自:http://www.jb51.net/article/71041.htm 如果不能設計一個合理的資料庫模型,不僅會增加客戶端和伺服器段程式的程式設計和維護的難度,而且將會影響系統實際執行的效能。所以,在一個系統開始實施之前,完備的資料庫模型的設計是必須的。 一、資料庫結構的設計 在一個系統分析、設計

資料庫優化 ------ 索引的使用問題

  最近,在工作的過程中,會時不時的碰到要不要新增索引的問題,於是結合自己的經歷,忙裡偷閒總結下,希望自已以後忘記了可以快速的記憶起來,同時也希望也可以幫助一些跟我一樣有需求的小夥伴。   一直以來,我總是不自覺的去想,到底什麼是索引?為什麼建立索引可以加快查詢的速度?直

$Django 資料庫圖片渲染設計 個人站點設計 截斷函式

1.資料庫圖片渲染設計 1.模型層 class User_info (AbstractUser): head_img = models.FileField (upload_to='test', default='test/2.jpg',null=True, blank=True) 2

簡單的資料庫優化

    不管用什麼樣的語言,資料庫是必不可少的,因此資料庫優化是必備的。 下面列舉幾條基本的簡單的資料庫優化,環境是php + mysql。 1.合理設定欄位屬性。 大家都知道資料庫中的表越小,在它上面執行的查詢也就會越快。因此合理設定欄位屬性,使資料庫表儘可

公司報表資料庫優化

報表系統優化 背景: 11.22早晨 剛放下揹包,收到一份郵件,郵件意思是公司報表資料庫慢,讓我幫忙看看。郵件還附帶了一個SQL文字,指出這個SQL慢。隨後電話了開發人員瞭解事情來龍去脈,原來是在一個月前 DB組幫他們遷移了報表資料庫,現在感覺這個新環境比沒遷移前還要慢(由於老環

資料庫優化技術

本篇文章為轉載文章 一、百萬級資料庫優化方案 1.對查詢進行優化,要儘量避免全表掃描,首先應考慮在 where 及 order by 涉及的列上建立索引。 2.應儘量避免在 where 子句中對欄位進行 null 值判斷,否則將導致引擎放棄使用索引而進行全表掃描,如: sel

資料庫優化設計(非常實用)

一、樹型關係的資料表        不少程式設計師在進行資料庫設計的時候都遇到過樹型關係的資料,例如常見的類別表,即一個大類,下面有若干個子類,某些子類又有子類這樣的情況。當類別不確定,使用者希望可以在任意類別下新增新的子類,或者刪除某個類別和其下的所有子類,而且預計以後其

【學習筆記】資料庫優化之索引(聚簇索引&非聚簇索引)

索引:對資料庫表中一列或多列的值進行排序的一種結構,通過索引可快速訪問資料庫表中的特定資訊,即通過索引對資料列的值進行結構化排序。 其中,索引包含聚簇索引和非聚簇索引 聚簇索引的順序就是資料的物理儲存順序 非聚簇索引的索引順序與資料物理排列順序無關 所以一個表