中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當前位置: 首頁 > news >正文

日本真人做爰無遮擋視頻免費網(wǎng)站網(wǎng)絡(luò)推廣培訓(xùn)去哪里好

日本真人做爰無遮擋視頻免費網(wǎng)站,網(wǎng)絡(luò)推廣培訓(xùn)去哪里好,張家港建設(shè)網(wǎng)站,wordpress導(dǎo)航網(wǎng)站主題大家使用 DolphinDB 創(chuàng)建數(shù)據(jù)庫和表時,有時對于分區(qū)列、分區(qū)類型和排序列的選擇并不十分清晰。如果不加注意,可能導(dǎo)致查詢速度變慢、數(shù)據(jù)丟失或插入錯誤等問題。合理地設(shè)置分區(qū)列、排序列和分區(qū)類型,有助于加快查詢速度,減少內(nèi)存使…

大家使用 DolphinDB 創(chuàng)建數(shù)據(jù)庫和表時,有時對于分區(qū)列、分區(qū)類型和排序列的選擇并不十分清晰。如果不加注意,可能導(dǎo)致查詢速度變慢、數(shù)據(jù)丟失或插入錯誤等問題。合理地設(shè)置分區(qū)列、排序列和分區(qū)類型,有助于加快查詢速度,減少內(nèi)存使用,并提高 CPU 利用率

以下內(nèi)容可以幫助大家更好地了解創(chuàng)建數(shù)據(jù)庫和表時需注意的細節(jié),優(yōu)化腳本質(zhì)量。

1. 分區(qū)與儲存結(jié)構(gòu)簡介

1.1 分區(qū)類型

分區(qū)是進行數(shù)據(jù)管理和提高分布式文件系統(tǒng)性能的重要手段之一。通過分區(qū)實現(xiàn)對大型表的有效管理。一個合理的分區(qū)策略能夠僅讀取查詢所需的數(shù)據(jù),以減少掃描的數(shù)據(jù)量,從而降低系統(tǒng)響應(yīng)延遲。

DolphinDB 支持多種分區(qū)類型: 范圍分區(qū)、哈希分區(qū)、值分區(qū)、列表分區(qū)與復(fù)合分區(qū)。選擇合適的分區(qū)類型,有助于用戶根據(jù)業(yè)務(wù)特點對數(shù)據(jù)進行均勻分割。

  • 范圍分區(qū)對每個分區(qū)區(qū)間創(chuàng)建一個分區(qū)。
  • 哈希分區(qū)利用哈希函數(shù)對分區(qū)列操作,方便建立指定數(shù)量的分區(qū)。
  • 值分區(qū)每個值創(chuàng)建一個分區(qū),例如股票交易日期、股票交易月等。
  • 列表分區(qū)是根據(jù)用戶枚舉的列表來進行分區(qū),比值分區(qū)更加靈活。
  • 復(fù)合分區(qū)適用于數(shù)據(jù)量特別大而且 SQL where 或 group by 語句經(jīng)常涉及多列。可使用 2 個或 3 個分區(qū)列,每個分區(qū)選擇都可以采用區(qū)間、值、哈?;蛄斜矸謪^(qū)。例如按股票交易日期進行值分區(qū), 同時按股票代碼進行范圍分區(qū)。

1.2 分區(qū)與數(shù)據(jù)讀寫的關(guān)系

DolphinDB 以分區(qū)為單位管理數(shù)據(jù),數(shù)據(jù)寫入和數(shù)據(jù)讀取都是按分區(qū)為單位進行的。

對于數(shù)據(jù)寫入,DolphinDB 會將數(shù)據(jù)按分區(qū)寫入磁盤,并且對于同一個分區(qū),不允許并發(fā)寫入數(shù)據(jù)。對于數(shù)據(jù)讀取,DolphinDB 會根據(jù)查詢條件進行分區(qū)剪枝,排除不符合條件的分區(qū),縮窄查詢范圍,只對符合查詢條件的分區(qū)進行讀取,分區(qū)字段和分區(qū)粒度的選擇很大程度上影響了查詢的效率。

1.3 儲存結(jié)構(gòu)

目前 DolphinDB 有 TSDB 和 OLAP 兩種儲存引擎。OLAP 為列式存儲引擎,將數(shù)據(jù)表中每個分區(qū)的每一列存為一個文件。數(shù)據(jù)在表中的存儲順序與數(shù)據(jù)寫入的順序一致,數(shù)據(jù)寫入有非常高的效率。TSDB 是基于 LSM 樹的存儲引擎,其儲存結(jié)構(gòu)為行列混存。每一個分區(qū)的數(shù)據(jù)寫在一個或多個 Level File 中。每一個 Level File 內(nèi)部的數(shù)據(jù)按照指定的列進行排序且創(chuàng)建塊索引。

1.3.1 排序列

排序列是 TSDB 引擎特有的結(jié)構(gòu),它在 TSDB 引擎的存儲和讀取流程中發(fā)揮著重要作用,包括分區(qū)內(nèi)數(shù)據(jù)索引和去重的雙重作用。在創(chuàng)建表時通過參數(shù) sortColumns 來定義排序列,sortColumns 的最后一列必須是時間類型,而除了最后一列之外的其他列被稱為 排序鍵(Sort Key),每個排序鍵獨特值對應(yīng)的數(shù)據(jù)按列順序存儲在一起。排序鍵字段的組合值作為索引鍵,為數(shù)據(jù)查詢提供了入口,能夠迅速定位數(shù)據(jù)塊的位置,從而降低查詢時間。在寫入過程中,每個事務(wù)中的數(shù)據(jù)會根據(jù) sortColumns 進行排序和去重。

TSDB 引擎的分區(qū)內(nèi)索引包括每個索引鍵和字段組合的入口信息以及稀疏索引(最大值,最小值,個數(shù)和)信息。當索引鍵個數(shù) X 字段數(shù)很大時,索引數(shù)據(jù)會很大,這對寫入性能,查詢性能和內(nèi)存使用都會產(chǎn)生重大影響,可以通過對排序鍵進行哈希降維來減少索引數(shù)量。

2. 建庫建表時容易忽略的細節(jié)

2.1 使用 TSDB 引擎時單個索引鍵對應(yīng)的數(shù)據(jù)條數(shù)過少

使用 TSDB 引擎建表時要指定排序列字段,但是隨意設(shè)置排序列可能會導(dǎo)致索引鍵對應(yīng)的數(shù)據(jù)過少,會使查詢變慢。推薦索引鍵對應(yīng)的數(shù)據(jù)量大于一萬行,當每個索引鍵對應(yīng)很少的數(shù)據(jù)量的時候,會產(chǎn)生以下幾個問題:

  • 由于數(shù)據(jù)總量不變,導(dǎo)致索引鍵非常多,索引信息占據(jù)大量內(nèi)存。
  • 數(shù)據(jù)碎片化存儲,導(dǎo)致數(shù)據(jù)讀寫效率降低。
  • 由于數(shù)據(jù)按照 block 進行壓縮,而 block 是每個索引鍵對應(yīng)數(shù)據(jù)按照數(shù)據(jù)量進行劃分的,若每個 block 數(shù)據(jù)量很少,壓縮率也會降低。

2.1.1 錯誤例子

例子:股票數(shù)據(jù)(假設(shè)股票數(shù)量為 5000 支,每天記錄 2000 萬條,每天數(shù)據(jù)量為 800 MB),按交易日期字段作為值分區(qū)條件。

情況1:只使用 TradeTime 作為排序列會導(dǎo)致索引鍵數(shù)量過多,但是每個索引鍵對應(yīng)的數(shù)據(jù)量又特別少。

單個排序列時,該列就稱為排序鍵,一個分區(qū)的索引鍵數(shù)量計算公式:索引鍵數(shù)量 = 每個分區(qū)內(nèi)的排序鍵獨特值數(shù)量。

以下例子中,每個分區(qū)索引鍵數(shù)量 = TradeTime 去重后的數(shù)量。由于 TradeTime 為股票交易時間,即使按秒級別計算一天也有 4 * 3600 = 14400 個獨特值,實際上 TradeTime 為毫秒級,故索引鍵數(shù)量遠大于 14400 。

db=database("dfs://testDB1",VALUE, 2020.01.01..2021.01.01,engine="TSDB")
colName = `SecurityID`TradeDate`TradeTime`TradePrice`TradeQty`TradeAmount`BuyNo`SellNo
colType = `SYMBOL`DATE`TIME`DOUBLE`INT`DOUBLE`INT`INT
tbSchema = table(1:0, colName, colType)
db.createPartitionedTable(table=tbSchema, tableName=`pt1, partitionColumns=`TradeDate, sortColumns=`TradeTime, keepDuplicates=ALL)

假設(shè)交易時間為半秒級,索引鍵數(shù)量為 28800 個,每個索引鍵對應(yīng)的行數(shù)為 694。

情況2:使用 SecurityID、TradeTime 作為 sortColumns 會導(dǎo)致索引鍵數(shù)量和股票代碼數(shù)量一樣。

多個 sortColumns 時索引鍵計算公式:索引鍵數(shù)量 = 每個分區(qū)內(nèi)的除去最后一列外其余字段獨特值組合值數(shù)量。

以下例子中,每個分區(qū)索引鍵的數(shù)量為 SecurityID 獨特值的數(shù)量,即 5000 個。

db=database("dfs://testDB1",VALUE, 2020.01.01..2021.01.01,engine="TSDB")
colName = `SecurityID`TradeDate`TradeTime`TradePrice`TradeQty`TradeAmount`BuyNo`SellNo
colType = `SYMBOL`DATE`TIME`DOUBLE`INT`DOUBLE`INT`INT
tbSchema = table(1:0, colName, colType)
db.createPartitionedTable(table=tbSchema, tableName=`pt2, partitionColumns=`TradeDate, sortColumns=`SecurityID`TradeTime, keepDuplicates=ALL)

假設(shè)股票數(shù)量為 5000 只,索引鍵數(shù)量為 5000 個,每個索引鍵對應(yīng)的行數(shù)為 4000。

2.1.2 解決方案

對于上述例子中的情況可以通過以下方案解決。

情況1:只有一個 sortColumns 字段時不選擇時間相關(guān)的或者去重后數(shù)量過多的字段。比如將 TradeTime 替換為 SecurityID 作為 sortColumn。

該方案中,每個分區(qū)索引鍵數(shù)量 = SecurityID 去重后的數(shù)量 = 5000。每個索引鍵對應(yīng)的行數(shù)為 4000 和上述例子中的情況2一樣。

db=database("dfs://testDB1",VALUE, 2020.01.01..2021.01.01,engine="TSDB")
colName = `SecurityID`TradeDate`TradeTime`TradePrice`TradeQty`TradeAmount`BuyNo`SellNo
colType = `SYMBOL`DATE`TIME`DOUBLE`INT`DOUBLE`INT`INT
tbSchema = table(1:0, colName, colType)
db.createPartitionedTable(table=tbSchema, tableName=`pt3, partitionColumns=`TradeDate, sortColumns=`SecurityID, keepDuplicates=ALL)

還可以對 SecurityID 排序列進行哈希降維。每個分區(qū)索引鍵數(shù)量 = 哈希降維后的數(shù)量(500)。每個索引鍵對應(yīng)的行數(shù)為 40000。

db=database("dfs://testDB1",VALUE, 2020.01.01..2021.01.01,engine="TSDB")
colName = `SecurityID`TradeDate`TradeTime`TradePrice`TradeQty`TradeAmount`BuyNo`SellNo
colType = `SYMBOL`DATE`TIME`DOUBLE`INT`DOUBLE`INT`INT
tbSchema = table(1:0, colName, colType)
db.createPartitionedTable(table=tbSchema, tableName=`pt4, partitionColumns=`TradeDate, sortColumns=`SecurityID keepDuplicates=ALL,sortKeyMappingFunction=[hashBucket{,500}])

情況2:有多個 sortColumns 字段時,可以配置 sortKeyMappingFunction 參數(shù)進行哈希降維(會影響相關(guān) sortColumns 字段的點查性能,但是會提升范圍查詢性能)。如果每個分區(qū)內(nèi)除最后一個時間列外,其余字段組合數(shù)量超過 1000 ,可以配置 sortKeyMappingFunction 參數(shù)進行哈希降維。

使用 SecurityID、TradeTime 作為 sortColumn 并配置 sortKeyMappingFunction 參數(shù)進行哈希降維。

多個 sortColumn 時索引鍵計算公式:索引鍵數(shù)量 = 每個分區(qū)內(nèi)的除去最后一列外其余字段去重(或者哈希降維)后數(shù)量相乘。

以下例子中,每個分區(qū)索引鍵數(shù)量 = 哈希降維后的數(shù)量(500)。每個索引鍵對應(yīng)的行數(shù)為 40000。

db=database("dfs://testDB1",VALUE, 2020.01.01..2021.01.01,engine="TSDB")
colName = `SecurityID`TradeDate`TradeTime`TradePrice`TradeQty`TradeAmount`BuyNo`SellNo
colType = `SYMBOL`DATE`TIME`DOUBLE`INT`DOUBLE`INT`INT
tbSchema = table(1:0, colName, colType)
db.createPartitionedTable(table=tbSchema, tableName=`pt5, partitionColumns=`TradeDate, sortColumns=`SecurityID`TradeTime, keepDuplicates=ALL,sortKeyMappingFunction=[hashBucket{,500}])

2.1.3 性能測試結(jié)果

按照上述五種建表方案進行建表,然后導(dǎo)入 10 天的數(shù)據(jù)(每天 2000 萬條記錄)測試其查詢性能。

范圍查詢:

select avg(TradePrice) from pt where TradeDate between 2020.01.04 and 2020.01.05
排序列每個分區(qū)索引鍵數(shù)平均耗時(ms)最大耗時(ms)
TradeTime28,800167.9215.1
SecurityID、TradeTime500046.368.6
SecurityID500047.766.9
SecurityID(哈希降維)5006.68.5
SecurityID(哈希降維)、TradeTime5006.77.9

點查詢 1(TradeDate + SecurityID):

select avg(TradePrice) from pt where TradeDate = 2020.01.04 and SecurityID=`600
排序列每個分區(qū)索引鍵數(shù)平均耗時(ms)最大耗時(ms)
TradeTime28,8002002.62562.8
SecurityID、TradeTime50004.04.7
SecurityID50003.44.7
SecurityID(哈希降維)5006.58.5
SecurityID(哈希降維)、TradeTime5007.78.3

點查詢 2(TradeDate + SecurityID + TradeTime):

select TradePrice from pt where TradeDate = 2020.01.04 and SecurityID=`3740 and TradeTime =09:30:00.000
排序列每個分區(qū)索引鍵數(shù)平均耗時(ms)最大耗時(ms)
TradeTime28,8001.42.1
SecurityID、TradeTime50001.52.6
SecurityID50001.42.3
SecurityID(哈希降維)5005.07.3
SecurityID(哈希降維)、TradeTime5006.28.0

通過上述性能測試實驗結(jié)果,可以得出結(jié)論:排序列設(shè)置不合理,查詢字段中沒有排序列字段,查詢性能將大幅下降。對于范圍查詢索引鍵對應(yīng)的數(shù)據(jù)過少,會影響其性能,可以通過哈希降維大幅提升性能(點查詢性能會略微下降)。

2.2 值(VALUE)分區(qū)字段為含特殊字符的字符串

值(VALUE)分區(qū)字段為字符串類型時,追加的分區(qū)列數(shù)據(jù)不能包含空格、“/n”、 “/r”、“/t”等特殊字符。如果后續(xù)插入的數(shù)據(jù)對應(yīng)字段有特殊字符,會導(dǎo)致數(shù)據(jù)插入失敗。

2.2.1 錯誤例子

建表時未考慮后續(xù)將設(shè)置為值(VALUE)分區(qū)字段的列內(nèi)是否包含特殊字符,導(dǎo)致數(shù)據(jù)插入該列時因存在特殊字符而失敗。

n=1000
ID=take(["1","2","3"], n);
x=rand(1.0, n);
t=table(ID, x);
//將ID列作為值分區(qū)
db=database(directory="dfs://valuedb", partitionType=VALUE, partitionScheme=["1"])
pt = db.createPartitionedTable(t, `pt, `ID);
pt.append!(t);
n=1000
ID=take(["1 12","2.12","3   12"], n);
x=rand(1.0, n);
t=table(ID, x);
pt.append!(t);

上述代碼會報錯:A string or symbol value-partitioning column can't contain any invisible character。

2.2.2 解決方案

對于前述例子中的錯誤,如果這些不可見的特殊字符無意義,可以在插入前刪除。如果有意義,可以將該字段設(shè)置為哈希(HASH)分區(qū)來替代值分區(qū)方案。哈希(HASH)分區(qū)的數(shù)量需要按照具體數(shù)據(jù)量進行設(shè)置,避免分區(qū)粒度過大或者過小?;蛘邔?yīng)字段數(shù)據(jù)進行處理后插入。

2.3 范圍(RANGE)分區(qū)時范圍設(shè)置不合理導(dǎo)致插入數(shù)據(jù)丟失

采用范圍(RANGE)分區(qū)策略時,如果插入數(shù)據(jù)的范圍(RANGE)分區(qū)字段的值在預(yù)定義的分區(qū)范圍外,那么這條記錄將不會被插入到表中。tableInsert會返回插入記錄的條數(shù)以此判斷是否有數(shù)據(jù)在范圍(RANGE)分區(qū)外而沒有存入分區(qū)表中。

2.3.1 錯誤例子

以下例子中,第 2 行 ID 和第 6 行 partitionScheme 的設(shè)置存在范圍不一致的情況。

n=1000000
ID=rand(20, n)//數(shù)據(jù)范圍是0-20
x=rand(1.0, n)
t=table(ID, x);
//設(shè)置分區(qū)時RANGE范圍是0-5,5-10
db=database(directory="dfs://rangedb", partitionType=RANGE, partitionScheme=0 5 10)pt = db.createPartitionedTable(t, `pt, `ID);
//tableInsert之后只有在0-10部分的數(shù)據(jù)才被插入,其余的都被丟棄。
tableInsert(pt,t);

上述例子通過 tableInsert 插入后返回 499972 條(遠小于 1000000)。

2.3.2 解決方案

由于 partitionScheme 設(shè)置為 0 5 10,導(dǎo)致只有 0-10 部分數(shù)據(jù)插入成功,其余部分數(shù)據(jù)丟失。因此應(yīng)該設(shè)置合適的分區(qū)范圍,考慮后續(xù)數(shù)據(jù)的范圍?;蛘呖梢酝ㄟ^ addRangePartitions 函數(shù)后續(xù)添加分區(qū)范圍。

2.4 分區(qū)粒度過小

分區(qū)類型或者分區(qū)字段設(shè)置不合理會導(dǎo)致分區(qū)粒度過小。分區(qū)粒度過小可能會導(dǎo)致以下問題:

  • 如果查詢范圍較大,會報錯 "The number of partitions relevant to the query is too large."
  • 使用 TSDB 引擎時,Level File 索引緩存(LevelFileIndexCache)大量被占用,可能導(dǎo)致所有使用 TSDB 引擎的數(shù)據(jù)庫的查詢變慢。
  • 查詢和計算作業(yè)往往會生成大量的子任務(wù),增加數(shù)據(jù)節(jié)點和控制節(jié)點之間及控制節(jié)點之間的通訊和調(diào)度成本。
  • 造成很多低效的磁盤訪問(小文件讀寫),導(dǎo)致系統(tǒng)負荷過重。
  • 所有分區(qū)的元數(shù)據(jù)都會駐留在控制節(jié)點的內(nèi)存中,過多的分區(qū)可能會導(dǎo)致控制節(jié)點內(nèi)存不足。

因此,建議每個分區(qū)未壓縮前的數(shù)據(jù)量不要小于 100 MB。

2.4.1 錯誤例子

例子:股票行情數(shù)據(jù)(每天 5000 萬條記錄),先按日期分區(qū)然后將股票代碼字段按值分區(qū)。選擇使用 TradeDate、SecurityID 二級分區(qū),而且 SecurityID 是值分區(qū),假設(shè)全是國內(nèi)股票,一天分區(qū)數(shù)量就達到 5000+。每天數(shù)據(jù)量為 3 GB(內(nèi)存中),每個分區(qū)大小約為 0.6 MB。

1.默認最大查詢分區(qū)數(shù)為 65536,假設(shè)每天 5000 個股票,查詢 14 天的數(shù)據(jù)就會報錯The number of partitions relevant to the query is too large。

2.Level File 索引緩存容量默認是最大內(nèi)存的5%,雖然單個分區(qū)的 Level File 索引(LevelFileIndex) 較小,但是如果查詢分區(qū)數(shù)非常多,會導(dǎo)致馬上占滿 Level File 索引緩存。占滿 Level File 索引緩存之后會導(dǎo)致查詢效率大幅度下降。

db1 = database(, VALUE, 2020.01.01..2021.01.01)
db2 = database(, VALUE, `a`b)
db = database(directory="dfs://testDB1", partitionType=COMPO, partitionScheme=[db1, db2], engine="TSDB")
colName = `SecurityID`TradeDate`TradeTime`TradePrice`TradeQty`TradeAmount`BuyNo`SellNo
colType = `SYMBOL`DATE`TIME`DOUBLE`INT`DOUBLE`INT`INT
tbSchema = table(1:0, colName, colType)
db.createPartitionedTable(table=tbSchema, tableName=`pt, partitionColumns=`TradeDate`SecurityID, sortColumns=`SecurityID`TradeTime, keepDuplicates=ALL)

2.4.2 解決方案

對于上述例子先按日期分區(qū),然后將股票代碼字段 HASH 分區(qū)(需要根據(jù)每天的量估計 HASH 多少個分區(qū),一般一個分區(qū)占用內(nèi)存應(yīng)控制在 100MB-1GB 之間),每天只有 25 個分區(qū),每天數(shù)據(jù)量為 3 GB(內(nèi)存中),每個分區(qū)大小約為 120 MB。

db1 = database(, VALUE, 2020.01.01..2021.01.01)
db2 = database(, HASH, [SYMBOL, 25])
db = database(directory="dfs://testDB2", partitionType=COMPO, partitionScheme=[db1, db2], engine="TSDB")
colName = `SecurityID`TradeDate`TradeTime`TradePrice`TradeQty`TradeAmount`BuyNo`SellNo
colType = `SYMBOL`DATE`TIME`DOUBLE`INT`DOUBLE`INT`INT
tbSchema = table(1:0, colName, colType)
db.createPartitionedTable(table=tbSchema, tableName=`pt, partitionColumns=`TradeDate`SecurityID, sortColumns=`SecurityID`TradeTime, keepDuplicates=ALL)

2.4.3 性能測試結(jié)果

按照上述兩種建表方案進行建表,然后導(dǎo)入 10 天的數(shù)據(jù)(每天 5000 萬條記錄)測試其范圍查詢性能。

select avg(TradePrice) from pt where TradeDate=2020.01.04
建表方案平均耗時(ms)最大耗時(ms)
日期值分區(qū)+股票代碼值分區(qū)214.4378.1
日期值分區(qū)+股票代碼哈希分區(qū)13.620.5

通過上述性能測試實驗結(jié)果,可以得出結(jié)論:如果分區(qū)粒度過小會導(dǎo)致查詢效率過低,建庫建表時要選擇合適的分區(qū)粒度。

2.5 分區(qū)粒度過大

分區(qū)類型或者分區(qū)字段設(shè)置不合理會導(dǎo)致分區(qū)粒度過大。若分區(qū)粒度過大,可能造成:

  • 多個工作線程并行時內(nèi)存不足。
  • 系統(tǒng)頻繁地在磁盤和工作內(nèi)存之間切換,影響性能。
  • 無法有效利用 DolphinDB 多節(jié)點多分區(qū)的優(yōu)勢,將本可以并行計算的任務(wù)轉(zhuǎn)化成了順序計算任務(wù)。

2.5.1 錯誤例子

以下例子中的股票行情數(shù)據(jù)(每天 5000 萬條記錄),直接按日期分區(qū),一天數(shù)據(jù)大約有 3 GB(內(nèi)存中)。

//按交易日期分區(qū)
db= database("dfs://testDB1", VALUE, 2020.01.01..2021.01.01)
colName = `SecurityID`TradeDate`TradeTime`TradePrice`TradeQty`TradeAmount`BuyNo`SellNo
colType = `SYMBOL`DATE`TIME`DOUBLE`INT`DOUBLE`INT`INT
tbSchema = table(1:0, colName, colType)
//每天只有1個分區(qū),假設(shè)每天數(shù)據(jù)量為3GB(內(nèi)存中),每個分區(qū)大小約為3GB,分區(qū)粒度過大
db.createPartitionedTable(table=tbSchema, tableName=`pt, partitionColumns=`TradeDate)

2.5.2 解決方案

對以下例子中的股票行情數(shù)據(jù),先按日期分區(qū)然后將股票代碼字段哈希分區(qū)(需要根據(jù)每天的量估計需要哈希的分區(qū)數(shù)量,一般一個分區(qū)內(nèi)存中大小 100 MB - 1 GB 之間)。

//先按交易日期分區(qū),然后按股票代碼進行哈希分區(qū)
db1 = database(, VALUE, 2020.01.01..2021.01.01)
db2 = database(, HASH, [SYMBOL, 25])
db = database(directory="dfs://testDB2", partitionType=COMPO, partitionScheme=[db1, db2])
colName = `SecurityID`TradeDate`TradeTime`TradePrice`TradeQty`TradeAmount`BuyNo`SellNo
colType = `SYMBOL`DATE`TIME`DOUBLE`INT`DOUBLE`INT`INT
tbSchema = table(1:0, colName, colType)
//每天只有25個分區(qū),假設(shè)每天數(shù)據(jù)量為3GB(內(nèi)存中),每個分區(qū)大小約為120MB
db.createPartitionedTable(table=tbSchema, tableName=`pt, partitionColumns=`TradeDate`SecurityID)

2.5.3 性能測試結(jié)果

按照上述兩種建表方案進行建表,然后導(dǎo)入 10 天的數(shù)據(jù)(每天 5000 萬條記錄)測試其點查性能。

select avg(TradePrice) from pt where SecurityID=`600
建表方案平均耗時(ms)最大耗時(ms)
日期值分區(qū)560.4683.1
日期值分區(qū)+股票代碼哈希分區(qū)31.240.8

通過上述性能測試實驗結(jié)果,可以得出結(jié)論:如果分區(qū)粒度過大會導(dǎo)致查詢效率過低,建庫建表時要選擇合適的分區(qū)粒度。

2.6 使用維度表存儲大數(shù)據(jù)量的表

維度表會將整個表加載入內(nèi)存,并且不會自動釋放( 2.00.11 版本之前)。如果創(chuàng)建維度表時未考慮之后的大數(shù)據(jù)量,會導(dǎo)致查詢速度隨數(shù)據(jù)量增加而下降,并占用大量內(nèi)存。

2.6.1 錯誤例子

使用維度表存儲超過 20 萬條記錄的數(shù)據(jù)或難以估算的數(shù)據(jù)。

例子:以每天產(chǎn)生 2000 萬條記錄的股票數(shù)據(jù)為例,如果使用僅有一個分區(qū)的維度表,不到幾天該表里就會有幾億條數(shù)據(jù)。假設(shè)每天的數(shù)據(jù)量為 800 MB(內(nèi)存中),讀取維度表數(shù)據(jù)時會將整個維度表加載入內(nèi)存,不到幾天,內(nèi)存就會被大量占用。

db= database("dfs://testDB1", VALUE, 2020.01.01..2021.01.01)
colName = `SecurityID`TradeDate`TradeTime`TradePrice`TradeQty`TradeAmount`BuyNo`SellNo
colType = `SYMBOL`DATE`TIME`DOUBLE`INT`DOUBLE`INT`INT
tbSchema = table(1:0, colName, colType)
db.createTable(tbSchema,`dt)

所以在預(yù)估數(shù)據(jù)量明確或較少時,可以使用維度表;預(yù)估數(shù)據(jù)量較多時,應(yīng)該使用分區(qū)表。

2.6.2 解決方案

上述例子中每天產(chǎn)生 2000 萬條股票數(shù)據(jù)。為了處理這些數(shù)據(jù),可以使用分區(qū)表:

  1. 首先按交易日期進行分區(qū)。
  2. 然后按股票代碼進行哈希分區(qū),每天只會有 25 個分區(qū)。

以下代碼為使用分區(qū)表方案建表:

db1 = database(, VALUE, 2020.01.01..2021.01.01)
db2 = database(, HASH, [SYMBOL, 25])
db = database(directory="dfs://testDB2", partitionType=COMPO, partitionScheme=[db1, db2])
colName = `SecurityID`TradeDate`TradeTime`TradePrice`TradeQty`TradeAmount`BuyNo`SellNo
colType = `SYMBOL`DATE`TIME`DOUBLE`INT`DOUBLE`INT`INT
tbSchema = table(1:0, colName, colType)
db.createPartitionedTable(table=tbSchema, tableName=`pt, partitionColumns=`TradeDate`SecurityID)

2.6.3 性能測試結(jié)果

按照上述兩種建表方案進行建表,然后導(dǎo)入一天的數(shù)據(jù)( 2000 萬條記錄)測試其點查性能。

select avg(TradePrice) from tb where SecurityID=`600
建表方案平均耗時(ms)最大耗時(ms)
維度表1385.51545.2
日期值分區(qū)+股票代碼哈希分區(qū)36.060.3

通過上述性能測試實驗結(jié)果,可以得出結(jié)論:預(yù)估數(shù)據(jù)量明確或較少時,可以使用維度表;預(yù)估數(shù)據(jù)量較多時,應(yīng)該使用分區(qū)表。如果數(shù)據(jù)量非常多時使用維度表,其查詢性能將非常差。

2.7 分區(qū)字段選擇不合理導(dǎo)致查詢速度慢

如果經(jīng)常查詢的字段沒有設(shè)置為分區(qū)字段,而且查詢語句中沒有涉及分區(qū)字段,會導(dǎo)致數(shù)據(jù)庫無法進行分區(qū)剪枝,并因掃描所有數(shù)據(jù)使查詢緩慢。

2.7.1 錯誤例子

例子:對于以下例子中的股票數(shù)據(jù),只按股票代碼進行分區(qū),如果該數(shù)據(jù)經(jīng)常按交易日期和股票代碼進行查詢,只設(shè)置股票代碼作為分區(qū)列不但會導(dǎo)致按交易日期進行查詢時會掃描所有分區(qū),而且會導(dǎo)致分區(qū)大小因為每天有數(shù)據(jù)插入不斷變大。

db = database("dfs://testDB1",HASH, [SYMBOL, 25])
colName = `SecurityID`TradeDate`TradeTime`TradePrice`TradeQty`TradeAmount`BuyNo`SellNo
colType = `SYMBOL`DATE`TIME`DOUBLE`INT`DOUBLE`INT`INT
tbSchema = table(1:0, colName, colType)
db.createPartitionedTable(table=tbSchema, tableName=`pt, partitionColumns=`SecurityID)

2.7.2 解決方案

對于上述例子中的股票數(shù)據(jù),按交易日期和股票代碼進行分區(qū)。如果該數(shù)據(jù)經(jīng)常按交易日期和股票代碼進行查詢,可以設(shè)置交易日期和股票代碼作為分區(qū)列。

db1 = database(, VALUE, 2020.01.01..2021.01.01)
db2 = database(, HASH, [SYMBOL, 25])
db = database("dfs://testDB2", partitionType=COMPO, partitionScheme=[db1, db2])
colName = `SecurityID`TradeDate`TradeTime`TradePrice`TradeQty`TradeAmount`BuyNo`SellNo
colType = `SYMBOL`DATE`TIME`DOUBLE`INT`DOUBLE`INT`INT
tbSchema = table(1:0, colName, colType)
db.createPartitionedTable(table=tbSchema, tableName=`pt, partitionColumns=`TradeDate`SecurityID)

2.7.3 性能測試結(jié)果

按照上述兩種建表方案進行建表,然后導(dǎo)入 10 天的數(shù)據(jù)(每天 2000 萬條記錄)測試其點查性能。

select avg(TradePrice) from pt where SecurityID=`600 and TradeDate=2020.01.04
建表方案平均耗時(ms)最大耗時(ms)
股票代碼哈希分區(qū)174.5193.1
日期值分區(qū)+股票代碼哈希分區(qū)38.150.4

通過上述性能測試實驗結(jié)果,可以得出結(jié)論:選擇分區(qū)字段時,應(yīng)該考慮經(jīng)常查詢字段以提升查詢效率。

2.8 分區(qū)字段選擇不合理導(dǎo)致并發(fā)寫入沖突

為了最大程度優(yōu)化數(shù)據(jù)倉庫查詢、分析、計算的性能,DolphinDB 對事務(wù)作了一些限制:

  • 首先,一個事務(wù)只能包含寫或者讀,不能同時進行寫和讀。
  • 其次,一個寫事務(wù)可以跨越多個分區(qū),但是同一個分區(qū)不能被并發(fā)寫入。當一個分區(qū)被某一個事務(wù) A 鎖定之后,另一個事務(wù) B 試圖再次去鎖定這個分區(qū)時,系統(tǒng)立刻會拋出異常導(dǎo)致事務(wù) B 失敗回滾。

建庫建表時未考慮后續(xù)可能出現(xiàn)的并發(fā)寫入。出現(xiàn)并發(fā)寫入時,由于分區(qū)沖突,導(dǎo)致并發(fā)寫入失敗。

2.8.1 錯誤例子

以下例子中,由于建庫建表時未考慮后續(xù)出現(xiàn)的并發(fā)寫入,未將各個并發(fā)數(shù)據(jù)不同的字段設(shè)置為分區(qū),導(dǎo)致并發(fā)寫入沖突。

//假設(shè)后續(xù)并發(fā),是按照日期進行寫入,只按股票代碼進行分區(qū)
db = database("dfs://testDB",HASH, [SYMBOL, 25])
colName = `SecurityID`TradeDate`TradeTime`TradePrice`TradeQty`TradeAmount`BuyNo`SellNo
colType = `SYMBOL`DATE`TIME`DOUBLE`INT`DOUBLE`INT`INT
tbSchema = table(1:0, colName, colType)
//只按股票代碼進行分區(qū),而并發(fā)寫入按照日期進行會導(dǎo)致并發(fā)寫入沖突,報錯“has been owned by transaction”
db.createPartitionedTable(table=tbSchema, tableName=`pt, partitionColumns=`SecurityID)

以上建庫建表代碼按日期并發(fā)寫入時會報錯:xxx has been owned by transaction。

2.8.2 解決方案

對于上述情況有以下解決方法:

  1. 建庫建表時可以按照按日期分區(qū)的方式進行建庫建表,并行寫入程序也按日期劃分寫入數(shù)據(jù)。
  2. 根據(jù)分區(qū)情況調(diào)整并行寫入程序,避免寫入分區(qū)重合。
  3. 如果使用相關(guān) api 進行寫入,可以使用 api 中的并行寫入函數(shù),自動對寫入數(shù)據(jù)進行劃分,比如 c++ api 和 python api 中的 PartitionedTableAppender。

上述解決方法目的都是,避免同一個分區(qū)同時被多個寫入事務(wù)寫入的情況。

2.9 數(shù)據(jù)量與日俱增的表未使用日期字段分區(qū)

一些數(shù)據(jù)量隨日期不斷增加的表,沒有使用日期字段作為分區(qū)字段。數(shù)據(jù)量隨時間增加會導(dǎo)致分區(qū)過大,影響查詢性能。

2.9.1 錯誤例子

數(shù)據(jù)量隨日期不斷增加的表中,沒有把日期字段設(shè)為分區(qū)列。

例子:對于以下例子中的股票數(shù)據(jù),只按股票代碼分區(qū),導(dǎo)致按交易日期進行查詢時會掃描所有分區(qū),并且分區(qū)隨每天的數(shù)據(jù)插入不斷變大。

db = database("dfs://testDB1",HASH, [SYMBOL, 25])
colName = `SecurityID`TradeDate`TradeTime`TradePrice`TradeQty`TradeAmount`BuyNo`SellNo
colType = `SYMBOL`DATE`TIME`DOUBLE`INT`DOUBLE`INT`INT
tbSchema = table(1:0, colName, colType)
db.createPartitionedTable(table=tbSchema, tableName=`pt, partitionColumns=`SecurityID)

對于數(shù)據(jù)量隨日期不斷增加的表,應(yīng)將日期字段設(shè)為分區(qū)列。

2.9.2 解決方案

對于上述例子中的股票數(shù)據(jù),按照交易日期和股票代碼進行了分區(qū)。

這樣每個分區(qū)不會因為每天的數(shù)據(jù)插入而不斷變大。由于按照交易日期進行了分區(qū),新的分區(qū)會隨著日期變化而生成。

db1 = database(, VALUE, 2020.01.01..2021.01.01)
db2 = database(, HASH, [SYMBOL, 25])
db = database("dfs://testDB2", partitionType=COMPO, partitionScheme=[db1, db2])
colName = `SecurityID`TradeDate`TradeTime`TradePrice`TradeQty`TradeAmount`BuyNo`SellNo
colType = `SYMBOL`DATE`TIME`DOUBLE`INT`DOUBLE`INT`INT
tbSchema = table(1:0, colName, colType)
db.createPartitionedTable(table=tbSchema, tableName=`pt, partitionColumns=`TradeDate`SecurityID)

2.9.3 性能測試結(jié)果

按照上述兩種建表方案進行建表,然后導(dǎo)入 10 天的數(shù)據(jù)(每天 2000 萬條記錄)測試其點查性能。

select avg(TradePrice) from pt where SecurityID=`600 and TradeDate=2020.01.04
建表方案平均耗時(ms)最大耗時(ms)
股票代碼哈希分區(qū)174.5193.1
日期值分區(qū)+股票代碼哈希分區(qū)38.150.4

通過上述性能測試實驗結(jié)果,可以得出結(jié)論:對于數(shù)據(jù)量與日俱增的表應(yīng)使用日期字段作為分區(qū)字段,提升查詢效率。

2.10 使用 OLAP 引擎存儲寬表

因為 OLAP 引擎采用列式存儲,每個分區(qū)的每一列數(shù)據(jù)都存儲為一個文件。列文件過多時,會出現(xiàn)讀寫時的性能瓶頸,因此 OLAP 引擎不適于存儲列數(shù)過多的寬表。如果使用 OLAP 引擎存儲數(shù)據(jù),表的列數(shù)應(yīng)低于 100。

由于 TSDB 引擎采用行列混存的存儲策略,在存儲寬表數(shù)據(jù)時,其產(chǎn)生的物理文件數(shù)量少于 OLAP 引擎。

2.10.1 錯誤例子

例子:每個 ID 有 200 個因子,每個因子為一列,該表一共 203 列。使用 OLAP 引擎存儲該表。

db= database("dfs://testDB1", VALUE, 2020.01.01..2021.01.01)
//202行的寬表,使用OLAP引擎(默認為OLAP)
colName = `ID`Date`Time
colName.append!(take("factor"+string(0..200),200))
colType = `SYMBOL`DATE
colType.append!(take(["DOUBLE"],200))
tbSchema = table(1:0, colName, colType)
db.createPartitionedTable(table=tbSchema, tableName=`pt, partitionColumns=`Date)

2.10.2 解決方案

對于上述例子中表列數(shù)為 203,采用 TSDB 引擎存儲該表能夠避免讀寫時可能出現(xiàn)的性能瓶頸。

db= database("dfs://testDB2", VALUE, 2020.01.01..2021.01.01,engine="TSDB")
//203行的寬表,使用TSDB引擎
colName = `ID`Date`Time
colName.append!(take("factor"+string(0..200),200))
colType = `SYMBOL`DATE`TIME
colType.append!(take(["DOUBLE"],200))
tbSchema = table(1:0, colName, colType)
db.createPartitionedTable(table=tbSchema, tableName=`pt, partitionColumns=`Date,sortColumns=`ID`Time)

2.10.3 性能測試結(jié)果

按照上述兩種建表方案進行建表,然后導(dǎo)入 10 天的數(shù)據(jù)(每天 200 萬條記錄)測試其點查性能。

select avg(factor2) from pt where ID=`60 and Date=2020.01.04
引擎平均耗時(ms)最大耗時(ms)
OLAP 引擎62.695.9
TSDB 引擎1.21.3

通過上述性能測試實驗結(jié)果,可以得出結(jié)論:對于列數(shù)大于 100 列的表可以使用 TSDB 引擎,提升查詢效率。

3. 總結(jié)

本文介紹了使用 DolphinDB 進行建庫建表時,最容易忽略的 10 個細節(jié)。這些錯誤用法的產(chǎn)生,是由于對 DolphinDB 分區(qū)機制和數(shù)據(jù)庫引擎原理不了解導(dǎo)致的。如果想進一步了解 DolphinDB 原理層面的細節(jié),可以參考:TSDB 存儲引擎詳解 (dolphindb.cn)、數(shù)據(jù)庫分區(qū) (dolphindb.cn)、分布式表數(shù)據(jù)更新原理和性能 (dolphindb.cn)。

最后,我們來歸納一下建庫建表的要點:

  1. 根據(jù)業(yè)務(wù)特點選擇合適的引擎(比如寬表選擇TSDB引擎)
  2. 根據(jù)業(yè)務(wù)特點選擇分區(qū)字段和類型
  3. 根據(jù)分區(qū)大小在 100 MB - 1 GB 的原則設(shè)計分區(qū)粒度
  4. 根據(jù)業(yè)務(wù)特點完善對應(yīng)引擎獨有的參數(shù)(比如TSDB引擎特有的排序列)
http://www.risenshineclean.com/news/48182.html

相關(guān)文章:

  • 深圳網(wǎng)站建設(shè) 網(wǎng)站設(shè)計亞馬遜查關(guān)鍵詞排名工具
  • 網(wǎng)站常用的藍色2023國內(nèi)外重大新聞事件10條
  • 品牌網(wǎng)站升級網(wǎng)絡(luò)營銷推廣策劃書
  • 在福州做搬家網(wǎng)站多少錢seo快速排名點擊
  • 邯鄲網(wǎng)站建設(shè)的地方考研培訓(xùn)班集訓(xùn)營
  • 南通網(wǎng)站建設(shè)報價社交網(wǎng)絡(luò)推廣方法
  • 手機制作網(wǎng)站主頁軟件下載百度網(wǎng)盤
  • 網(wǎng)站被取消備案福州seo博客
  • 個人做網(wǎng)站要備案嗎安徽網(wǎng)站關(guān)鍵詞優(yōu)化
  • 做阿里巴巴網(wǎng)站圖片大全企業(yè)官網(wǎng)網(wǎng)站
  • 羅湖做網(wǎng)站58優(yōu)化網(wǎng)站關(guān)鍵詞的技巧
  • 做煤的網(wǎng)站app網(wǎng)站需要怎么優(yōu)化比較好
  • 東莞公司建設(shè)網(wǎng)站如何在百度上推廣自己
  • 網(wǎng)站開發(fā)合同 下載襄陽seo推廣
  • 網(wǎng)站無法訪問百度網(wǎng)盤首頁
  • 網(wǎng)站權(quán)重分散怎樣建立網(wǎng)站平臺
  • 軟裝設(shè)計圖 效果圖溫州seo教程
  • 運營服務(wù)商官方網(wǎng)站百度首頁純凈版怎么設(shè)置
  • 成都設(shè)計院工資企業(yè)站seo價格
  • 太原網(wǎng)站建設(shè)技術(shù)托管鄭州seo哪家好
  • 福建設(shè)計院網(wǎng)站百度百度一下就知道
  • 去哪找想做網(wǎng)站的客戶2023年8月疫情嚴重嗎
  • 無錫高端網(wǎng)站建設(shè)寧波seo搜索引擎優(yōu)化公司
  • 網(wǎng)站換了域名還被k站不安仁網(wǎng)絡(luò)推廣
  • 整站排名優(yōu)化品牌怎么推廣網(wǎng)站鏈接
  • 專業(yè)做淘寶網(wǎng)站公司嗎seo是什么職業(yè)崗位
  • 部署在本地的wordpress太原網(wǎng)站優(yōu)化公司
  • 武昌網(wǎng)站建設(shè)推廣手段和渠道有哪些
  • 專業(yè)做網(wǎng)站app的公司有哪些有品質(zhì)的網(wǎng)站推廣公司
  • 如何網(wǎng)站建設(shè)seo優(yōu)化排名百度教程