<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      [NewLife.XCode]分表分庫(百億級大數據存儲)

      NewLife.XCode是一個有15年歷史的開源數據中間件,支持netcore/net45/net40,由新生命團隊(2002~2019)開發完成并維護至今,以下簡稱XCode。

      整個系列教程會大量結合示例代碼和運行日志來進行深入分析,蘊含多年開發經驗于其中,代表作有百億級大數據實時計算項目。

      開源地址:https://github.com/NewLifeX/X (求star, 938+)

       

      XCode是重度充血模型,以單表操作為核心,不支持多表關聯Join,復雜查詢只能在where上做文章,整個select語句一定是from單表,因此對分表操作具有天然優勢!

      ?。?nbsp;閱讀本文之前,建議回顧《百億級性能》,其中“索引完備”章節詳細描述了大型數據表的核心要點。

       

      100億數據其實并不多,一個比較常見的數據分表分庫模型:

      MySql數據庫8主8從,每服務器8個庫,每個庫16張表,共1024張表(從庫也有1024張表) ,每張表1000萬到5000萬數據,整好100億到500億數據!

       

      例程剖析 

      例程位置:https://github.com/NewLifeX/X/tree/master/Samples/SplitTableOrDatabase 

      新建控制臺項目,nuget引用NewLife.XCode后,建立一個實體模型(修改Model.xml):

      <Tables Version="9.12.7136.19046" NameSpace="STOD.Entity" ConnName="STOD" Output="" BaseClass="Entity" xmlns:xs="http://www.w3.org/2001/XMLSchema-instance" xs:schemaLocation="http://www.newlifex.com https://raw.githubusercontent.com/NewLifeX/X/master/XCode/ModelSchema.xsd" xmlns="http://www.newlifex.com/ModelSchema.xsd">
        <Table Name="History" Description="歷史">
          <Columns>
            <Column Name="ID" DataType="Int32" Identity="True" PrimaryKey="True" Description="編號" />
            <Column Name="Category" DataType="String" Description="類別" />
            <Column Name="Action" DataType="String" Description="操作" />
            <Column Name="UserName" DataType="String" Description="用戶名" />
            <Column Name="CreateUserID" DataType="Int32" Description="用戶編號" />
            <Column Name="CreateIP" DataType="String" Description="IP地址" />
            <Column Name="CreateTime" DataType="DateTime" Description="時間" />
            <Column Name="Remark" DataType="String" Length="500" Description="詳細信息" />
          </Columns>
          <Indexes>
            <Index Columns="CreateTime" />
          </Indexes>
        </Table>
      </Tables>

      在Build.tt上右鍵運行自定義工具,生成實體類“歷史.cs”和“歷史.Biz.cs”。不用修改其中代碼,待會我們將借助該實體類來演示分表分庫用法。

      為了方便,我們將使用SQLite數據庫,因此不需要配置任何數據庫連接,XCode檢測到沒有名為STOD的連接字符串時,將默認使用SQLite。

      此外,也可以通過指定名為STOD的連接字符串,使用其它非SQLite數據庫。

       

      按數字散列分表分庫

      大量訂單、用戶等信息,可采用crc16散列分表,我們把該實體數據拆分到4個庫共16張表里面:

      static void TestByNumber()
      {
          XTrace.WriteLine("按數字分表分庫");
      
          // 預先準備好各個庫的連接字符串,動態增加,也可以在配置文件寫好
          for (var i = 0; i < 4; i++)
          {
              var connName = $"HDB_{i + 1}";
              DAL.AddConnStr(connName, $"data source=numberData\\{connName}.db", null, "sqlite");
              History.Meta.ConnName = connName;
      
              // 每庫建立4張表。這一步不是必須的,首次讀寫數據時也會創建
              //for (var j = 0; j < 4; j++)
              //{
              //    History.Meta.TableName = $"History_{j + 1}";
      
              //    // 初始化數據表
              //    History.Meta.Session.InitData();
              //}
          }
      
          //!!! 寫入數據測試
      
          // 4個庫
          for (var i = 0; i < 4; i++)
          {
              var connName = $"HDB_{i + 1}";
              History.Meta.ConnName = connName;
      
              // 每庫4張表
              for (var j = 0; j < 4; j++)
              {
                  History.Meta.TableName = $"History_{j + 1}";
      
                  // 插入一批數據
                  var list = new List<History>();
                  for (var n = 0; n < 1000; n++)
                  {
                      var entity = new History
                      {
                          Category = "交易",
                          Action = "轉賬",
                          CreateUserID = 1234,
                          CreateTime = DateTime.Now,
                          Remark = $"[{Rand.NextString(6)}]向[{Rand.NextString(6)}]轉賬[¥{Rand.Next(1_000_000) / 100d}]"
                      };
      
                      list.Add(entity);
                  }
      
                  // 批量插入。兩種寫法等價
                  //list.BatchInsert();
                  list.Insert(true);
              }
          }
      }

      通過 DAL.AddConnStr 動態向系統注冊連接字符串:

      var connName = $"HDB_{i + 1}";

      DAL.AddConnStr(connName, $"data source=numberData\\{connName}.db", null, "sqlite");

      連接名必須唯一,且有規律,后面要用到。數據庫名最好也有一定規律。 

      使用時通過Meta.ConnName指定后續操作的連接名,Meta.TableName指定后續操作的表名,本線程有效,不會干涉其它線程。

      var connName = $"HDB_{i + 1}";
      History.Meta.ConnName = connName;

      History.Meta.TableName = $"History_{j + 1}";

      注意,ConnName/TableName改變后,將會一直維持該參數,直到修改為新的連接名和表名。

      指定表名連接名后,即可在本線程內持續使用,后面使用批量插入技術,給每張表插入一批數據。

       

      運行效果如下:

       

       

       

       

      連接字符串指定的numberData目錄下,生成了4個數據庫,每個數據庫生成了4張表,每張表內插入1000行數據。

      指定不存在的數據庫和數據表時,XCode的反向工程將會自動建表建庫,這是它獨有的功能。(因異步操作,密集建表建庫時可能有一定幾率失敗,重試即可)

       

      按時間序列分表分庫

      日志型的時間序列數據,特別適合分表分庫存儲,定型拆分模式是,每月一個庫每天一張表。

      static void TestByDate()
      {
          XTrace.WriteLine("按時間分表分庫,每月一個庫,每天一張表");
      
          // 預先準備好各個庫的連接字符串,動態增加,也可以在配置文件寫好
          var start = DateTime.Today;
          for (var i = 0; i < 12; i++)
          {
              var dt = new DateTime(start.Year, i + 1, 1);
              var connName = $"HDB_{dt:yyMM}";
              DAL.AddConnStr(connName, $"data source=timeData\\{connName}.db", null, "sqlite");
          }
      
          // 每月一個庫,每天一張表
          start = new DateTime(start.Year, 1, 1);
          for (var i = 0; i < 365; i++)
          {
              var dt = start.AddDays(i);
              History.Meta.ConnName = $"HDB_{dt:yyMM}";
              History.Meta.TableName = $"History_{dt:yyMMdd}";
      
              // 插入一批數據
              var list = new List<History>();
              for (var n = 0; n < 1000; n++)
              {
                  var entity = new History
                  {
                      Category = "交易",
                      Action = "轉賬",
                      CreateUserID = 1234,
                      CreateTime = DateTime.Now,
                      Remark = $"[{Rand.NextString(6)}]向[{Rand.NextString(6)}]轉賬[¥{Rand.Next(1_000_000) / 100d}]"
                  };
      
                  list.Add(entity);
              }
      
              // 批量插入。兩種寫法等價
              //list.BatchInsert();
              list.Insert(true);
          }
      }

      時間序列分表看起來比數字散列更簡單一些,分表邏輯清晰明了。

       

       

       

       

       

       例程遍歷了今年的365天,在連接字符串指定的timeData目錄下,生成了12個月份數據庫,然后每個庫里面按月生成數據表,每張表插入1000行模擬數據。

       

      綜上,分表分庫其實就是在操作數據庫之前,預先設置好 Meta.ConnName/Meta.TableName,其它操作不變!

       

      分表查詢

      說到分表,許多人第一反應就是,怎么做跨表查詢?

      不好意思,不支持!

      只能在多張表上各自查詢,如果系統設計不合理,甚至可能需要在所有表上進行查詢。

      不建議做視圖union,那樣會無窮無盡,業務邏輯還是放在代碼中為好,數據庫做好存儲與基礎計算。

       

      分表查詢的用法與分表添刪改一樣:

      static void SearchByDate()
      {
          // 預先準備好各個庫的連接字符串,動態增加,也可以在配置文件寫好
          var start = DateTime.Today;
          for (var i = 0; i < 12; i++)
          {
              var dt = new DateTime(start.Year, i + 1, 1);
              var connName = $"HDB_{dt:yyMM}";
              DAL.AddConnStr(connName, $"data source=timeData\\{connName}.db", null, "sqlite");
          }
      
          // 隨機日期。批量操作
          start = new DateTime(start.Year, 1, 1);
          {
              var dt = start.AddDays(Rand.Next(0, 365));
              XTrace.WriteLine("查詢日期:{0}", dt);
      
              History.Meta.ConnName = $"HDB_{dt:yyMM}";
              History.Meta.TableName = $"History_{dt:yyMMdd}";
      
              var list = History.FindAll();
              XTrace.WriteLine("數據:{0}", list.Count);
          }
      
          // 隨機日期。個例操作
          start = new DateTime(start.Year, 1, 1);
          {
              var dt = start.AddDays(Rand.Next(0, 365));
              XTrace.WriteLine("查詢日期:{0}", dt);
              var list = History.Meta.ProcessWithSplit(
                  $"HDB_{dt:yyMM}",
                  $"History_{dt:yyMMdd}",
                  () => History.FindAll());
      
              XTrace.WriteLine("數據:{0}", list.Count);
          }
      }

       

      仍然是通過設置 Meta.ConnName/Meta.TableName 來實現分表分庫。日志輸出可以看到查找了哪個庫哪張表。

      這里多了一個 History.Meta.ProcessWithSplit  ,其實是快捷方法,在回調內使用連接名和表名,退出后復原。

       

      分表分庫后,最容易犯下的錯誤,就是使用時忘了設置表名,在錯誤的表上查找數據,然后怎么也查不到……

       

      分表策略

      根據這些年的經驗:

      • Oracle適合單表1000萬~1億行數據,要做分區
      • MySql適合單表1000萬~5000萬行數據,很少人用MySql分區

      如果統一在應用層做拆分,數據庫只負責存儲,那么上面的方案適用于各種數據庫。

      同時,單表數據上限,就是大家常問的應該分為幾張表?在系統生命周期內(一般1~2年),確保拆分后的每張表數據總量在1000萬附近最佳。

      根據《百億級性能》,常見分表策略如下:

      • 日志型時間序列表,如果每月數據不足1000萬,則按月分表,否則按天分表。缺點是數據熱點極為明顯,適合熱表、冷表、歸檔表的梯隊架構,優點是批量寫入和抽取性能顯著;
      • 狀態表(訂單、用戶等),按Crc16哈希分表,以1000萬為準,決定分表數量,向上取整為2的指數倍(為了好算)。數據冷熱均勻,利于單行查詢更新,缺點是不利于批量寫入和抽取;
      • 混合分表。訂單表可以根據單號Crc16哈希分表,便于單行查找更新,作為寬表擁有各種明細字段,同時還可以基于訂單時間建立一套時間序列表,作為冗余,只存儲單號等必要字段。這樣就解決了又要主鍵分表,又要按時間維度查詢的問題。缺點就是訂單數據需要寫兩份,當然,時間序列表只需要插入單號,其它更新操作不涉及。

      至于是否需要分庫,主要由存儲空間以及性能要求決定。

       

      分表與分區對比

      還有一個很常見的問題,為什么使用分表而不是分區?

      大型數據庫Oracle、MSSQL、MySql都支持分區,前兩者較多使用分區,MySql則較多分表。

      分區和分表并沒有本質的不同,兩者都是為了把海量數據按照一定的策略拆分存儲,以優化寫入和查詢。

      • 分區除了能建立子索引外,還可以建立全局索引,而分表不能建立全局索引;
      • 分區能跨區查詢,但非常非常慢,一不小心就掃描所有分區;
      • 分表架構,很容易做成分庫,支持輕易擴展到多臺服務器上去,分區只能要求數據庫服務器更強更大;
      • 分區主要由DBA操作,分表主要由程序員控制;

       

       

      !??!某項目使用XCode分表功能,已經過生產環境三年半考驗,日均新增4000萬~5000萬數據量,2億多次添刪改,總數據量數百億。

       

      博文答疑

      2019年9月9日晚上19點,釘釘企業群“新生命團隊”,視頻直播博文答疑。

      今晚之后,如有問題,可以提問:https://github.com/NewLifeX/X/issues

       

       

       

      系列教程

      NewLife.XCode教程系列[2019版]

      1. 增刪改查入門??焖僬宫F用法,代碼配置連接字符串
      2. 數據模型文件。建立表格字段和索引,名字以及數據類型規范,推薦字段(時間,用戶,IP)
      3. 實體類詳解。數據類業務類,泛型基類,接口
      4. 功能設置。連接字符串,調試開關,SQL日志,慢日志,參數化,執行超時。代碼與配置文件設置,連接字符串局部設置
      5. 反向工程。自動建立數據庫數據表
      6. 數據初始化。InitData寫入初始化數據
      7. 高級增刪改。重載攔截,自增字段,Valid驗證,實體模型(時間,用戶,IP)
      8. 臟數據。如何產生,怎么利用
      9. 增量累加。高并發統計
      10. 事務處理。單表和多表,不同連接,多種寫法
      11. 擴展屬性。多表關聯,Map映射
      12. 高級查詢。復雜條件,分頁,自定義擴展FieldItem,查總記錄數,查匯總統計
      13. 數據層緩存。Sql緩存,更新機制
      14. 實體緩存。全表整理緩存,更新機制
      15. 對象緩存。字典緩存,適用用戶等數據較多場景。
      16. 百億級性能。字段精煉,索引完備,合理查詢,充分利用緩存
      17. 實體工廠。元數據,通用處理程序
      18. 角色權限。Membership
      19. 導入導出。Xml,Json,二進制,網絡或文件
      20. 分表分庫。常見拆分邏輯
      21. 高級統計。聚合統計,分組統計
      22. 批量寫入。批量插入,批量Upsert,異步保存
      23. 實體隊列。寫入級緩存,提升性能。
      24. 備份同步。備份數據,恢復數據,同步數據
      25. 數據服務。提供RPC接口服務,遠程執行查詢,例如SQLite網絡版
      26. 大數據分析。ETL抽取,調度計算處理,結果持久化 
      posted @ 2019-09-09 09:07  大石頭  閱讀(7171)  評論(28)    收藏  舉報
      主站蜘蛛池模板: julia无码中文字幕一区| 亚洲中文字幕无码中文字| 欧美成人精品在线| 国产综合一区二区三区麻豆| 国产一区二区三区美女| 中文字幕日韩人妻一区| 国产人伦精品一区二区三| 吉木乃县| 亚洲最大色综合成人av| 中文字幕亚洲无线码一区女同| 新巴尔虎左旗| 在线观看美女网站大全免费| 在线看免费无码av天堂| 中文字幕国产日韩精品| 久久大香萑太香蕉av黄软件| 精品国产福利一区二区| 在国产线视频A在线视频| 白嫩人妻精品一二三四区| 丰满少妇在线观看网站| 一面膜上边一面膜下边视频| 婷婷六月色| 蜜桃在线一区二区三区| 日韩高清亚洲日韩精品一区二区| 99久久成人亚洲精品观看| 国产三级精品三级在线看| 亚洲成av人片无码天堂下载| 广安市| 国产成人亚洲综合91精品| 国产69精品久久久久乱码免费| 欧美成人影院亚洲综合图| 一区二区三区四区国产综合| 欧美激情一区二区三区成人| 师宗县| 国产av剧情无码精品色午夜| 欧美牲交a欧美牲交aⅴ图片| 久久精品蜜芽亚洲国产av| 国产超碰无码最新上传| 久女女热精品视频在线观看| 黄色特级片一区二区三区| 久爱无码精品免费视频在线观看| а天堂中文最新一区二区三区|