MySQL優化大全

               

 1. 優化SQL

  1)通過show status瞭解各種sql的執行頻率

        show status like 'Com_%'
        瞭解 Com_select,Com_insert 的執行次數
   2)  通過Explain分析低效的sql語句
   3)   建立合適的索引
   4)   通過show status like 'Handler_%'查看索引的使用情況
         handler_read_key:根據索引讀取行的請求數。如果該值很大,說明你的查詢和表都建立了很好的索引,表明索引效率的很高
         Handler_read_rnd_key:根據固定位置讀取行的請求數。如果你執行很多需要排序的查詢,該值會很高。你可能有很多需要完整表掃描的查詢,或者你使用了不正確的索引用來多表查詢。

         Handler read rnd next:從數據文件中讀取行的請求數。如果你在掃描很多表,該值會很大。通常情況下這意味着你的表沒有做好索引,或者你的查詢語句沒有使用好索引字段。

   5)   定期分析表和檢查表
         analyze table test_table和check table test_table
         然後查看Msg_text字段的值是否是ok
   6)定期優化表 optimize table test_table
         如果對錶的可變字段varchar blob,text等進行了很多更改, 則應用OPTIMIZE優化。

         在多數的設置中,您根本不需要運行OPTIMIZE TABLE。即使您對可變長度的行進行了大量的更新,您也不需要經常運行,每週一次或每月一次即可,只對特定的表運行。
       OPTIMIZE TABLE只對MyISAM, BDB和InnoDB表起作用。
       對於MyISAM表,OPTIMIZE TABLE按如下方式操作:
       如果表已經刪除或分解了行,則修復表。
       如果未對索引頁進行分類,則進行分類。
       如果表的統計數據沒有更新(並且通過對索引進行分類不能實現修復),則進行更新。
   7)  優化 order by orgroup by等

    詳細內容:SQL優化大全

2. 優化數據庫對象

1)選擇表合適存儲引擎:

            MyISAM:  應用時以讀和插入操作爲主,只有少量的更新和刪除,並且對事務的完整性,併發性要求不是很高的.

            Innodb: 事務處理,以及併發條件下要求數據的一致性。除了插入和查詢外,包括很多的更新和刪除。(Innodb有效地降低刪除和更新導致的鎖定)。對於支持事務的InnoDB類型的表來說,影響速度的主要原因是AUTOCOMMIT默認設置是打開的,而且程序沒有顯式調用BEGIN 開始事務,導致每插入一條都自動提交,嚴重影響了速度。可以在執行sql前調用begin,多條sql形成一個事物(即使autocommit打開也可以),將大大提高性能。

            Memory:數據保存在RAM,快速訪問數據。要求表不能太大或者對mysql異常終止後不用恢復數據的

            Merge:      
2)優化表的數據類型,選擇合適的數據類型:

           原則:更小通常更好,簡單就好,所有字段都得有默認值,儘量避免null:

           例如:數據庫表設計時候更小的佔磁盤空間儘可能使用更小的整數類型.(mediumint就比int更合適)

           比如時間字段:datetime和timestamp, datetime佔用8個字節,而timestamp佔用4個字節,只用了一半,而timestamp表示的範圍是1970—2037適合做更新時間

  MySQL可以很好的支持大數據量的存取,但是一般說來,數據庫中的表越小,在它上面執行的查詢也就會越快。因此,在創建表的時候,爲了獲得更好的性能,我們可以將表中字段的寬度設得儘可能小。例如,在定義郵政編碼這個字段時,如果將其設置爲CHAR(255),顯然給數據庫增加了不必要的空間,甚至使用VARCHAR這種類型也是多餘的,因爲CHAR(6)就可以很好的完成任務了。同樣的,如果可以的話,我們應該使用MEDIUMINT而不是BIGIN來定義整型字段。
  另外一個提高效率的方法是在可能的情況下,應該儘量把字段設置爲NOT NULL,這樣在將來執行查詢的時候,數據庫不用去比較NULL值。
  對於某些文本字段,例如省份或者性別,我們可以將它們定義爲ENUM類型。因爲在MySQL中,ENUM類型被當作數值型數據來處理,而數值型數據被處理起來的速度要比文本類型快得多。這樣,我們又可以提高數據庫的性能。

3) 字符串數據類型:char,varchar,text選擇區別
       (1)長度的區別
,char範圍是0~255,varchar最長是64k,但是注意這裏的64k是整個row的長度,要考慮到其它的column,還有如果存在not null的時候也會佔用一位,對不同的字符集,有效長度還不一樣,比如utf8的,最多21845,還要除去別的column,但是varchar在一般情況下存儲都夠用了。如果遇到了大文本,考慮使用text,最大能到4G。 

      (2) 效率來說基本是char>varchar>text,但是如果使用的是Innodb引擎的話,推薦使用varchar代替

     (3)默認值  charchar和varchar可以有默認值,text不能指定默認值

4)MySQL中float數據類型的問題

      (1) .FLOAT或DOUBLE列與具有數值類型的數值進行比較,不能使用等式(=)比較.這個是因爲浮點數精度的問題,會產生誤差。

  (2)對貨幣等對精度敏感的數據,應該用定點數表示或存儲

      數據庫選擇合適的數據類型存儲還是很有必要的,對性能有一定影響。這裏在零碎記錄兩筆,對於int類型的,如果不需要存取負值,最好加上unsigned;對於經常出現在where語句中的字段,考慮加索引,整型的尤其適合加索引。

 5)在InnoDB數據表設計中,我們需要注意幾點:

    1. 顯式的定義一個 INT 類型自增字段的主鍵,這個字段可以僅用於做主鍵,不做其他用途
    2. 如果不顯式定義主鍵的話,可能會導致InnoDB每次都需要對新數據行進行排序,嚴重損害性能
    3. 儘量保證不對主鍵字段進行更新修改,防止主鍵字段發生變化,引發數據存儲碎片,降低IO性能
    4. 如果需要對主鍵字段進行更新,請將該字段轉變成一個唯一索引約束字段,另外創建一個沒有其他業務意義的自增字段做主鍵
    5. 主鍵字段類型儘可能小,能用SMALLINT就不用INT,能用INT就不用BIGINT
    6. 主鍵字段放在數據表的第一順序

3. 優化索引

  索引是提高數據庫性能的常用方法,它可以令數據庫服務器以比沒有索引快得多的速度檢索特定的行,尤其是在查詢語句當中包含有MAX(), MIN()ORDERBY這些命令的時候,性能提高更爲明顯.

    那該對哪些字段建立索引呢?一般說來,索引應建立在那些將用於JOIN, WHERE判斷和ORDER BY排序的字段上。儘量不要對數據庫中某個含有大量重複的值的字段建立索引。對於一個ENUM類型的字段來說,出現大量重複值是很有可能的情況,例如customerinfo中的“province”..字段,在這樣的字段上建立索引將不會有什麼幫助;相反,還有可能降低數據庫的性能。我們在創建表的時候可以同時創建合適的索引,也可以使用ALTER TABLECREATE INDEX在以後創建索引

1). 普通索引

        普通索引(由關鍵字KEY或INDEX定義的索引)的唯一任務是加快對數據的訪問速度。因此,應該只爲那些最經常出現在查詢條件(WHERE column = …)或排序條件(ORDER BY column)中的數據列創建索引。只要有可能,就應該選擇一個數據最整齊、最緊湊的數據列(如一個整數類型的數據列)來創建索引。

2). 唯一索引

        普通索引允許被索引的數據列包含重複的值。比如說,因爲人有可能同名,所以同一個姓名在同一個”員工個人資料”數據表裏可能出現兩次或更多次。
如果能確定某個數據列將只包含彼此各不相同的值,在爲這個數據列創建索引的時候就應該用關鍵字UNIQUE把它定義爲一個唯一索引。這麼做的好處:一是簡化了MySQL對這個索引的管理工作,這個索引也因此而變得更有效率;二是MySQL會在有新記錄插入數據表時,自動檢查新記錄的這個字段的值是否已經在某個記錄的這個字段裏出現過了;如果是,MySQL將拒絕插入那條新記錄。也就是說,唯一索引可以保證數據記錄的唯一性。事實上,在許多場合,人們創建唯一索引的目的往往不是爲了提高訪問速度,而只是爲了避免數據出現重複。

3). 主索引

        在前面已經反覆多次強調過:必須爲主鍵字段創建一個索引,這個索引就是所謂的”主索引”。主索引與唯一索引的唯一區別是:前者在定義時使用的關鍵字是PRIMARY而不是UNIQUE。

 4). 外鍵索引

         如果爲某個外鍵字段定義了一個外鍵約束條件,MySQL就會定義一個內部索引來幫助自己以最有效率的方式去管理和使用外鍵約束條件。

 5). 複合索引

        索引可以覆蓋多個數據列,如像INDEX(columnA, columnB)索引。這種索引的特點是MySQL可以有選擇地使用一個這樣的索引。如果查詢操作只需要用到columnA數據列上的一個索引,就可以使用複合索引INDEX(columnA, columnB)。不過,這種用法僅適用於在複合索引中排列在前的數據列組合。比如說,INDEX(A, B, C)可以當做A或(A, B)的索引來使用,但不能當做B、C或(B, C)的索引來使用。

4. 表鎖的問題

     跟性能相關的最重要的區別就是 MyISAM 和 InnoDB 實現的鎖機制不一樣! MyISAM 使用的是表鎖, 而 InnoDB實現的是行鎖。

1) MyISAM爲表級鎖

        由於MyISAM寫進程優先獲得鎖,使得讀鎖請求靠後等待隊列。不僅如此,即使讀請求先到鎖等待隊列,寫請求後 到,寫鎖也會插到讀鎖請求之前!這是因爲MySQL認爲寫請求一般比讀請求要重要。
        如果在大量更新操作的情況下,使得很難獲得讀鎖。從而造成阻塞。
        所以MyIsam不適合做大量更新操作的原因

2 )INNODB的行鎖是基於索引實現,如果不通過索引訪問數據,Innodb會使用表鎖

 

表級鎖更適合以查詢爲主,只有少量按索引條件更新數據的應用。

行級鎖更適合於有大量按索引條件併發更新少量不同數據,同時又併發查詢。因爲只鎖定要操作的行, 所以可以多個線程同時操作不同的行(只要不操作其他線程已經鎖定的行)。


5. MySQL server服務器配置優化

   1)使用show variables 瞭解服務器參數
   2)show status 瞭解服務器運行狀態,如鎖等待情況,當前連接數等
   3)影響mysql性能的重要參數:

         key_buffer_size設置索引塊的緩存大小:key_buffer_size是對MyISAM表性能影響最大的一個參數

        通過:

    mysql> show global status like 'key_read%';
+-------------------+------------+
| Variable_name     | Value      |
+-------------------+------------+
| Key_read_requests | 3465117712 |
| Key_reads         | 624        |
+-------------------+------------+

   Key_read_requests:從緩存讀取索引的請求次數。
   Key_reads:從磁盤讀取索引的請求次數。

   通常人們認爲Key_read_requests / Key_reads越大越好

    需要適當加大key_buffer_size 


         table_cache數據庫打開表的緩存數量 ,每個連接進來,都會至少打開一個表緩存。因此
         table_cache和max_connections有關, 例如 對於200個並行運行的連接,應該讓表的緩存至少是200 *N
         N 是可以執行查詢的一個連接中的表的最大數

    4)  還有innodb_buffer_pool_size等innodb參數的設置

6. 磁盤IO優化

  對於我們數據庫調優來說,磁盤I/O優化是首屈一指的調優重點,我們都知道木桶原理,短板絕對整體的好壞,而數據庫系統中這個短板正是由於我們使用的硬件設備裏最弱的磁盤所導致。很多時候,我們會發現系統中I/O累得要死,而CPU卻在那裏空閒等待,主要是由於I/O執行響應時間太長,處理讀寫 的速度遠遠趕落後於CPU的處理速度,這時我們會儘可能的讓操作放到內存中進行,由磁盤與CPU的關係,轉變成內存與CPU的關係。但是,我們始終不能回 避磁盤I/O的弱點,優化是必須的。

        磁盤搜索是巨大的性能瓶頸。當數據量變得非常大以致於緩存性能變得不可能有效時,該問題變得更加明顯。對於大數據庫,其中你或多或少地隨機訪問數據,你可以確 信對讀取操作需要至少一次硬盤搜索,寫操作需要多次硬盤搜索。要想使該問題最小化, 應使用搜索次數較少的磁盤。

1)使用磁盤陣列  RAID (廉價磁盤冗餘陣列)

         RAID就是按照一定的策略將數據分佈到若干物理磁盤上,這樣不僅增強了數據存儲的可靠性,而且提高數 據讀寫的性能 (RAID有不能的級別)
         1) 讀寫很頻繁的,可靠性要求也很高的,最好RAID 10
         2) 數據讀很頻繁,寫相對較少的,對可靠性一定要求的,選擇RAID 5

         3) 數據讀寫都很頻繁,但是可靠性要求不高的可以選擇RAID 0

   
2) 使用符號鏈接 分佈I/O

          MYSQL在默認的情況下,數據庫和數據表都存放在參數datadir定義的目錄下,這樣如果不使用RAID或者邏輯卷,所有的數據都存放在一個磁盤設備上,無法發揮多磁盤並 行讀寫的優勢。

         可以將表和數據庫從數據庫目錄移動到其它的位置並且用指向新位置的符號鏈接進行替換。推薦的方法只需要將數據庫通過符號鏈接指到不同的磁盤。符號鏈接表僅作爲是 最後的辦法。

        符號鏈接一個數據庫的方法是,首先在一些有空閒空間的硬盤上創建一個目錄,然後從 MySQL 數據目錄中創建它的一個符號鏈接。

      例如:

$ mkdir /dr1/databases/test$ ln -s /dr1/databases/test /path/to/datadir

      注意:只有 MyISAM 表完全支持符號鏈接。對於其它表類型,如果試圖在操作系統 中的文件上用前面的任何語句使用符號鏈接,可能會出現奇怪的問題。
對於 MyISAM 表的符號鏈接的處理如下:
     1. 在數據目錄指,一定會有表定義文件、數據文件和索引文件。數據文件和索引文件可 以移到別處和在數據目錄中符號鏈接替代。表定義文件不能進行符號鏈接替換。
     2. 可以分別通過符號鏈接將數據文件和索引文件指到不同的目錄。

     3. 如果 mysqld 沒有運行,符號鏈接可以從服務器命令行使用 ln -s 手動完成。同樣,通過使用 DATA DIRECTORY 和 INDEX DIRECTORY 選項創建表,你可以指示運行的 MySQL 服務器執行符號鏈接。
     4. myisamchk 不用數據文件或索引文件替換符號鏈接。它直接工作在符號鏈接指向的文件。任何臨時文件創建在數據文件或索引文件所處的目錄中。
     5. 註釋:當你刪掉一個表時,如果該表使用了符號鏈接,符號鏈接和該符號鏈接指向的 文件都被刪除掉。這就是你不應以系統 root 用戶運行 mysqld 或允許系統用戶對 MySQL數據庫目錄有寫訪問權限的原因。
     6. 如果你用 ALTER TABLE ... RENAME 重命名一個表並且不將表移到另一個數據庫,數據庫目錄中的符號鏈接被重新命名爲一個新名字並且數據文件和索引文件也相應地重新命名。
     7. 如果你用 ALTER TABLE ... RENAME 移動一個表到另一個數據庫,表移動到另一個數據庫目錄。舊的符號鏈接和其所指向的文件被刪除。換句話說,新表不再被鏈接。
     8. 如果不使用符號鏈接,你應對 mysqld 使用 --skip-symbolic-links 選項以確保沒有人能夠使用 mysqld 來刪除或重新命名數據目錄之外的文件。

    表符號鏈接還不支持以下操作:
    1. ALTER TABLE 忽略 DATA DIRECTORY 和 INDEX DIRECTORY 表選項。
    2. BACKUP TABLE 和 RESTORE TABLE 不考慮符號鏈接。
    3. .frm 文件必須絕不能是一個符號鏈接(如前面所述,只有數據和索引文件可以是符鏈接)。如果試圖這樣做(例如,生成符號鏈接)會產生不正確的結果。

3) 禁止操作系統更新文件的atime屬性

7. 應用優化

1 )使用連接池
對於訪問數據庫來說,建立連接的代價比較昂貴,因此,我們有必要建立 " 連接池 " 以提高訪問的性能。我們可以把連接當作對象或者設備,池中又有許多已經建立的連接,訪 問本來需要與數據庫的連接的地方,都改爲和池相連,池臨時分配連接供訪問使用,結果返 回後,訪問將連接交還。

2)減少對mysql的訪問,使用mem緩存等

3)負載均衡,複製分流查詢操作
           利用mysql的主從複製,分流更新操作和查詢操作
          1), 創建複製賬號:Gran replication slave on *.* to 'rel'@'10.0.1.2' identified by '123456'
          2), 修改主服務器的配置my.conf 開啓binlog和設置server-id
          3), 將主服務器的數據一致性恢復到從服務器,保證將要複製的數據時一隻的,否則出問題
          4), 在從服務器上修改配置my.conf
               server-id=2
               master-host=10.0.1.3
               master-user='rel'
               master-password='123456'
               master-port='3306'

          5), 從服務器啓動slave線程: start slave
          show processlist 查看。

4) 分佈式cluster 數據庫架構

8. 分庫分表

1)水平劃分
    如果某個表的數據太多,預期有上千條甚至上億以上,我們可以化整爲0:拆表。
    這裏就涉及到拆表的算法:
    記錄日誌的表,也可以按周或者按月來拆。
    記錄用戶信息的表,按用戶id的hash算法來拆。

2)垂直拆分
  如果表記錄數並不多,可能也就2、3萬條,但是字段卻很長,表佔用空間很大,檢索表時需要執行大量I/O,嚴重降低了性能。這個時候需要把大的字段拆分到另一個表,並且該表與原表是一對一的關係。  


分庫解決方案原則:

n安全性拆分:

將高安全性數據與低安全性數據分庫,這樣的好處第一是便於維護,第二是高安全性數據的數據庫參數配置可以以安全優先,而低安全性數據的參數配置以性能優先。參見運維優化相關部分。

n基於業務邏輯拆分

1)根據數據表的內容構成,業務邏輯拆分,便於日常維護和前端調用。

2)基於業務邏輯拆分,可以減少前端應用請求發送到不同數據庫服務器的頻次,從而減少鏈接開銷。

3)基於業務邏輯拆分,可保留部分數據關聯,前端web工程師可在限度範圍內執行關聯查詢。

n基於負載壓力拆分

           1)基於負載壓力對數據結構拆分,便於直接將負載分擔給不同的服務器。

2)基於負載壓力拆分,可能拆分後的數據庫包含不同業務類型的數據表,日常維護會有一定的煩惱。

n混合拆分組合

1)基於安全與業務拆分爲數據庫實例,但是可以使用不同端口放在同一個服務器上。

2)基於負載可以拆分爲更多數據庫實例分佈在不同數據庫上

如:

基於安全拆分出A數據庫實例,
基於業務拆分出B,C數據庫實例,
數據庫存在較高負載,基於負載拆分爲C1,C2,C3,C4等實例。
數據庫服務器完全可以做到 A+B+C1 爲一臺,C2,C3,C4各單獨一臺。



分表方案解決原則

1、一般數據量過大或者訪問壓力過大的數據表需要切分

          2、表的字段不宜過多。

n縱向分表

   單數據表字段過多,可將頻繁更新的整數數據與非頻繁更新的字符串數據切分

範例user表 ,個人簡介,地址,QQ號,聯繫方式,頭像 這些字段爲字符串類型,更新請求少; 最後登錄時間,在線時常,訪問次數,信件數這些字段爲整數型字段,更新頻繁,可以將後面這些更新頻繁的字段獨立拆出一張數據表,表內容變少,索引結構變少,讀寫請求變快。

n橫向切表

1)等分切表,如哈希切表或其他基於對某數字取餘的切表。等分切表的優點是負載很方便的分佈到不同服務器;缺點是當容量繼續增加時無法方便的擴容,需要重新進行數據的切分或轉表。而且一些關鍵主鍵不易處理。

2)遞增切表,比如每1kw用戶開一個新表,優點是可以適應數據的自增趨勢;缺點是往往新數據負載高,壓力分配不平均。

3)日期切表,適用於日誌記錄式數據,優缺點等同於遞增切表。

4)個人傾向於遞增切表,具體根據應用場景決定。


n熱點數據分表

1)將數據量較大的數據表中將讀寫頻繁的數據抽取出來,形成熱點數據表。通常一個龐大數據表經常被讀寫的內容往往具有一定的集中性,如果這些集中數據單獨處理,就會極大減少整體系統的負載。

2)熱點數據表與舊有數據關係

可以是一張冗餘表,即該表數據丟失不會妨礙使用,因源數據仍存在於舊有結構中。優點是安全性高,維護方便,缺點是寫壓力不能分擔,仍需要同步寫回原系統。

可以是非冗餘表,即熱點數據的內容原有結構不再保存,優點是讀寫效率全部優化;缺點是當熱點數據發生變化時,維護量較大。

具體方案選擇需要根據讀寫比例決定,在讀頻率遠高於寫頻率情況下,優先考慮冗餘表方案。

3)熱點數據表可以用單獨的優化的硬件存儲,比如昂貴的閃存卡或大內存系統。

4)熱點數據表的重要指標

熱點數據的定義需要根據業務模式自行制定策略,常見策略爲,按照最新的操作時間;按照內容豐富度等等。
數據規模,比如從1000萬條數據,抽取出100萬條熱點數據。
熱點命中率,比如查詢10次,多少次命中在熱點數據內。
理論上,數據規模越小,熱點命中率越高,說明效果越好。需要根據業務自行評估。

5)熱點數據表的動態維護
加載熱點數據方案選擇
定時從舊有數據結構中按照新的策略獲取
在從舊有數據結構讀取時動態加載到熱點數據
剔除熱點數據方案選擇
基於特定策略,定時將熱點數據中訪問頻次較少的數據剔除
如熱點數據是冗餘表,則直接刪除即可,如不是冗餘表,需要回寫給舊有數據結構。
6)通常,熱點數據往往是基於緩存或者key-value方案冗餘存儲,所以這裏提到的熱點數據表,其實更多是理解思路,用到的場合可能並不多….


9. 反範式設計(冗餘結構設計)

反範式設計的概念

無外鍵,無連表查詢。
便於分佈式設計,允許適度冗餘,爲了容量擴展允許適度開銷。
基於業務自由優化,基於i/o 或查詢設計,無須遵循範式結構設計。

冗餘結構設計所面臨的典型場景

原有展現程序涉及多個表的查詢,希望精簡查詢程序
數據表拆分往往基於主鍵,而原有數據表往往存在非基於主鍵的關鍵查詢,無法在分表結構中完成。
存在較多數據統計需求(count, sum等),效率低下。

冗餘設計方案

1)基於展現的冗餘設計

爲了簡化展現程序,在一些數據表中往往存在冗餘字段:

舉例,信息表message,存在字段fromuid,touid,msg,sendtime四個字段,其中touid+sendtime是複合索引。存在查詢爲select * from message where touid=$uid order by sendtime desc limit 0,30;

展示程序需要顯示發送者姓名,此時通常會在message表中增加字段fromusername,甚至有的會增加fromusersex,從而無需連表查詢直接輸出信息的發送者姓名和性別。這就是一種簡單的,爲了避免連表查詢而使用的冗餘字段設計。

2)基於展現的冗餘設計

涉及分表操作後,一些常見的索引查詢可能需要跨表,帶來不必要的麻煩。確認查詢請求遠大於寫入請求時,應設置便於查詢項的冗餘表。
冗餘表要點:
數據一致性,簡單說,同增,同刪,同更新。
可以做全冗餘,或者只做主鍵關聯的冗餘,比如通過用戶名查詢uid,再基於uid查詢源表。

實戰範例1
用戶分表,將用戶庫分成若干數據表
基於用戶名的查詢和基於uid的查詢都是高併發請求。
用戶分表基於uid分成數據表,同時基於用戶名做對應冗餘表。
如果允許多方式登陸,可以有如下設計方法
nuid,passwd,用戶信息等等,主數據表,基於uid分表
nukey,ukeytype,uid基於ukey分表,便於用戶登陸的查詢。分解成如下兩個SQL。
uselect uid from ulist_key_13 where ukey=’$username’ and ukeytype=‘login’;
uselect * from ulist_uid_23 where uid=$uid and passwd=’$passwd’;
nukeytype定義用戶的登陸依據,比如用戶名,手機號,郵件地址,網站暱稱等。Ukey+ukeytype 必須唯一。
n此種方式需要登陸密碼統一,對於第三方connect接入模式,可以通過引申額外字段完成。


實戰範例2:用戶遊戲積分排名
表結構uid,gameid,score參見前文實時積分排行。表內容巨大,需要拆表。
需求1:基於遊戲id查詢積分排行
需求2:基於用戶id查詢遊戲積分記錄
解決方案:建立完全相同的兩套表結構,其一以uid爲拆表主鍵,其二以gameid爲拆表主鍵,用戶提交積分時,向兩個數據結構同時提交。

實戰範例3:全冗餘查詢結構
主信息表僅包括 主鍵及備註memo字段(text類型),只支持主鍵查詢,可以基於主鍵拆表。所以需要展現和存儲的內容均在memo字段重體現。
對每一個查詢條件,建立查詢冗餘表,以查詢條件字段爲主鍵,以主信息表主鍵id爲內容。
日常查詢只基於查詢冗餘表,然後通過in的方式從主信息表獲得內容。
優點是結構擴展非常方便,只需要擴展新的查詢信息表即可,核心思路是,只有查詢才需要獨立的索引結構,展現無需獨立字段。
缺點是隻適合於相對固定的查詢架構,對於更加靈活的組合查詢束手無策


3)基於統計的冗餘結構

爲了減少會涉及大規模影響結果集的表數據操作,比如count,sum操作。應將一些統計類數據通過冗餘數據結構保存。
冗餘數據結構可能以字段方式存在,也可能以獨立數據表結構存在,但是都應能通過源數據表恢復。
實戰範例:
論壇板塊的發帖量,回帖量,每日新增數據等。
網站每日新增用戶數等。
參見Discuz論壇系統數據結構,有較多相關結構。
參見前文分段積分結構,是典型用於統計的冗餘結構。

後臺可以通過源數據表更新該數字。
Redis的Zset類型可以理解爲存在一種冗餘統計結構。


4)歷史數據表
歷史數據表對應於熱點數據表,將需求較少又不能丟棄的數據存入,僅在少數情況下被訪問。


           

再分享一下我老師大神的人工智能教程吧。零基礎!通俗易懂!風趣幽默!還帶黃段子!希望你也加入到我們人工智能的隊伍中來!https://blog.csdn.net/jiangjunshow

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章