欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

DolphinDB使用案例2:数据表分区

程序员文章站 2022-07-13 14:55:25
...
  • 关于分区,参见《数据库分区、分表、分库、分片》。

    数据表分区后,只是物理存储上分为不同的区,对于软件层面,代码处理的还是同一张表,代码不会因为分区而改变。

    当需要加载的表比系统内存大,就需要使用分区表。

    本文以btcusdt_1t.csv为例进行操作。决定分区数量的原则是:每个分区的大小不超过系统内存的四分之一。

  • 分区方式一:顺序分区

    分区方式:根据行的顺序,将btcusdt_1t.csv分成2区。

    # 构建分区数据库
    db = database("D:/DolphinDB/Data/seqdb", SEQ, 2) 
    # 将分区表并行载入
    btcusdt = loadTextEx(db, "btcusdt",,"D:/DolphinDB/Data/btcusdt_1t.csv")
    

    DolphinDB使用案例2:数据表分区

    1. database数据库创建函数
      database(directory, [partitionType], [partitionScheme], [locations])
      
      参数 意义 备注
      directory 保存数据库的目录地址 如果创建分布式文件系统中的数据库,以“dfs://”
      partitionType 六种分区类型 顺序分区(SEQ),范围分区(RANGE),哈希分区(HASH),数值分区(VALUE),列表分区(LIST)和组合分区(COMPO)
      partitionScheme 分区方案,描述分区是如何创建的 CHAR, SHORT, INT, DATE, MONTH, TIME, MINUTE, SECOND, DATETIME和SYMBOL
      locations 元组指定分区位置 元组中元素数量,应与分区类型、分区方案共同决定的分区数量相同。
      如果不指定,则所有分区属于当前节点

      分区类型与分区方案对应表:

      分区类型 分区符号 分区方案
      顺序分区 SEQ 整型标量。表示分区的数量。
      范围分区 RANGE 向量。 向量的任意两个相邻元素定义分区的范围。
      哈希分区 HASH 元组。第一个元素是分区列的数据类型,第二个元素是分区的数量。
      值分区 VALUE 向量。 向量的每个元素定义了一个分区。
      列表分区 LIST 向量。 向量的每个元素定义了一个分区。
      组合分区 COMPO 向量。向量的每个元素是一个数据库句柄。
    2. loadTextEx文本载入函数
      loadTextEx(dbHandle, tableName, partitionColumns, fileName, [delimiter=','], [schema])
      
      参数 意义 备注
      dbHandle 保存数据的分布式数据库的句柄 该数据库可以是本地文件系统的数据库,也可以是分布式文件系统的数据库
      tableName 表示分布式表的名字 一个字符串
      partitionColumns 表示分区列 字符串标量或向量。
      对于顺序分区,为空
      对于组合分区,是字符串向量
      filename 绝对路径的文件名 需载入的数据
      delimiter 表格列的分隔符
      schema 表对象,用于指定保存数据的表的结构 第一列的内容为字段名,第二列的内容为表示数据类型的字符串(不区分大小写)。

      loadTextEx函数采用Pipeline机制,一个线程解析数据,同时另一个线程不停的往数据库写。如此实现并行存储功能。

  • 分区方式二:范围分区

    分区方式:根据数据表中某列的范围进行分区。

    # 2.1根据某列(open)的范围进行分区
    db = database("D:/DolphinDB/Data/rangedb1", RANGE, 0 7500 8000)
    btcusdt = loadTextEx(db, "btcusdtrange", `open, "D:/DolphinDB/Data/btcusdt_1t.csv")
    

    **出现问题:**The data type of column [open] doesn’t match the database partition scheme.**原因:**浮点数不能作为分区方案,实际业务中 一般也不会用到。即便是下面的值分区也不可以。

    # 2.1(修正)改用时间作为分区方案
    db = database("D:/DolphinDB/Data/rangedb1", RANGE, 2018.03.29T00:00:00 2018.06.29T00:00:00 2018.10.12T00:00:00 )
    btcusdt = loadTextEx(db, "btcusdtrange", `candle_begin_time, "D:/DolphinDB/Data/btcusdt_1t.csv")
    

    举另外一个例子:

    # 2.2 另外一个例子
    n = 1000000
    ID= rand(10, n)
    x = rand(1.0, n)
    t = table(ID, x)
    db = database("D:/DolphinDB/Data/rangedb2", RANGE, 0 5 10)
    pt = db.createPartitionedTable(t, `pt, `ID)
    pt.append!(t)
    pt = loadTable(db, `pt)
    select count(*) from pt
    
    1. createPartitionedTable()创建磁盘或内存中的分区表
      createPartitionedTable(dbHandle, table, [tableName], partitionColumns)
      
      参数 意义 备注
      dbHandle 保存分区表的分布式数据库 可以是本地文件系统;
      或者分布式文件系统;
      如果没有指定,会是内存的分区表
      table 一个或一个系列的表 系统将会根据表的结构创建新的分区表
      tablename 保存到磁盘的分布式表的表名 或者是内存的分区表的表名
      partitionColumns 一个字符串或者字符串向量,表示分区列 对于多层次分区,是一个字符串向量

      append!savePartition来生成一个分区表,不能用于创建顺序分区的表。

      创建分区表时只会使用参数table的结构,并不会把table中的数据插入到新的分区表中。

  • 分区方式三:值分区

    分区方式:根据列中元素的值分区

    # 204个分区,每个分区代表2000.1到2016.12之间的每个月份
    n=1000000
    month=take(2000.01M..2016.12M, n)
    x=rand(1.0, n)
    t=table(month, x)
    db=database("C:/DolphinDB/Data/valuedb", VALUE, 2000.01M..2016.12M)
    pt = db.createPartitionedTable(t, `pt, `month)
    pt.append!(t)
    pt=loadTable(db,`pt)
    select count(x) from pt
    
  • 分区方式四:层次分区

    分区方式:一个数据库可以有二级或三级分区

    # 两级分区,第一级分区是值分区;第二级分区是范围分区
    n=1000000
    ID=rand(100, n)
    dates=2017.08.07..2017.08.11
    date=rand(dates, n)
    x=rand(10.0, n)
    t=table(ID, date, x)
    dbDate = database(, VALUE, 2017.08.07..2017.08.11)
    dbID=database(, RANGE, 0 50 100)
    db = database("C:/DolphinDB/Data/hierDB", HIER, [dbDate, dbID])
    pt = db.createPartitionedTable(t, `pt, `date`ID)
    pt.append!(t)
    pt=loadTable(db,`pt)
    select count(x) from pt