# 数据导入 > 此文档主要介绍 TuGraph 的数据导入功能。其中包括 CSV 格式的分隔符,jsonline 的格式示例,以及导入在线和离线的两种模式。 ## 1.简介 在图数据库服务安装成功后,您可以使用`lgraph_import`批量导入工具将现有数据导入 TuGraph。`lgraph_import`支持从 CSV 文件和 JSON 数据源导入数据。 > CSV 格式 ``` [movies.csv] id, name, year, rating tt0188766,King of Comedy,1999,7.3 tt0286112,Shaolin Soccer,2001,7.3 tt4701660,The Mermaid,2016,6.3 ``` > jsonline 格式 ```json ["tt0188766","King of Comedy",1999,7.3] ["tt0286112","Shaolin Soccer",2001,7.3] ["tt4701660","The Mermaid",2016,6.3] ``` TuGraph 支持两种导入模式: - _离线模式_:读取数据并将其导入指定服务器的数据文件,应仅在服务器离线时完成。 - _在线模式_:读取数据并将其发送到工作中的服务器,然后将数据导入其数据库。 ## 2.CSV文件格式分隔符 CSV格式的分隔符可以是单字符或多字符组成的字符串,其中不能包含`\r`或`\n`。注意不同的shell会对输入字符串做不同的处理,因此针对不同的shell输入参数可能需要不同的转义处理。 此外,`lgraph_import`还支持以下转义字符,以便输入特殊符号: | 转义符 | 说明 | | ------ | ---------------------------------------------------------------- | | \\ | 反斜杠`\\` | | \\a | 响铃,即 ASCII 码 0x07 | | \\f | form-feed,即 ASCII 码 0x0c | | \\t | 水平制表符,即 ASCII 码 0x09 | | \\v | 垂直制表符,即 ASCII 码 0x0b | | \\xnn | 两位十六进制数,表示一个字节,如\\x9A | | \\nnn | 三位八进制数,表示一个字节,如\\001, \\443,数值范围不能超过 255 | 例: ```bash $ ./lgraph_import -c ./import.config --delimiter "\001\002" ``` ## 3.配置文件 `lgraph_import`工具通过指定的配置文件进行环境配置。配置文件描述输入文件的路径、它们所代表的点/边以及点/边的格式。 ### 3.1.配置文件格式 配置文件包含两部分:schema 和 files。`schema`部分定义 label,`files`部分描述要导入的数据文件。 #### 3.1.1.关键字 - schema (数组形式) - label(必选,字符串形式) - type(必选,值只能是 VERTEX 或者 EDGE) - properties(数组形式,对于点必选,对于边如果没有属性可以不配置) - name(必选,字符串形式) - type (必选,BOOL,INT8,INT16,INT32,INT64,DATE,DATETIME,FLOAT,DOUBLE,STRING,BLOB) - optional(可选,代表该字段可以配置,也可以不配置) - index(可选,该字段是否需要建索引) - unique(可选,该字段是否建索引,并且是 unique 类型的,即全局唯一) - pair_unique(可选,该字段是否建索引,并且是 pari_unique 类型的,即两点间唯一,仅用于边索引)unique与pair_unique只能设置一个,同时设置并运行将会因为输入异常而终止 - primary (仅点配置,必选,主键字段,需指定一个 property,用来唯一确定一个点) - temproal (仅边配置,可选,指定时间戳属性用于存储层排序) - temporal_field_order (仅边配置,可选,默认为"ASC",表示升序,也可配置为"DESC",表示降序) - constraints (仅边配置,可选,数组形式,起点和终点的 label,不配置或者为空代表不限制) - detach_property (点边都可配置,可选,默认是`false`。`true` 代表属性数据单独存放,在内存不够,属性数据比较多的场景下可以减少io读放大) - files (数组形式) - path(必选,字符串,可以是文件路径或者目录的路径,如果是目录会导入此目录下的所有文件,需要保证有相同的 schema) - header(可选,数字,头信息占文件起始的几行,没有就是 0) - format(必须选,只能是 JSON 或者 CSV) - label(必选,字符串) - columns(数组形式) - SRC_ID (特殊字符串,仅边有,代表这列是起始点数据) - DST_ID (特殊字符串,仅边有,代表这列是目的点数据) - SKIP   (特殊字符串,代表跳过这列数据) - [property] - SRC_ID (仅边配置,值是起始点标签) - DST_ID (仅边配置,值是目的点标签) #### 3.1.2.索引长度 因为TuGraph对key的长度有限制,唯一索引不允许建立超过限制长度的索引,而非唯一索引会对超过长度限制的属性进行截断处理,并且在通过迭代器遍历非唯一索引时,拿到的key也是经过截断的,可能和预期不一致。针对不同类型的非唯一索引,截断长度是不同的。 ##### 3.1.2.1.unique索引 unique索引是全局唯一的,该索引key的最大长度是480bytes。primary作为特殊的unique索引,因此最大key的长度也是480bytes,超过无法建立索引。 ##### 3.1.2.2.pair_unique索引 pair_unique索引是指两点间唯一的索引,这种类型的索引只能创建于边的schema中,这种索引在用户指定的key后面加上了源点和目标点的vid,每个vid是5bytes长度。因此最大key的长度是470bytes,超过无法建立索引。 ##### 3.1.2.3.非唯一索引 非唯一索引是指既没有设置unique为1,也没有设置pair_unique为1的索引,在TuGraph的实现中,此类索引一个key可能映射到多个值,为了加速查找和写入,在用户指定的key后面加上了一组vid或euid中的最大值。其中对于创建于点中的非唯一索引,key后面跟着vid,每个vid是5bytes长度,因此最大长度是475bytes。 对于创建于边中的非唯一索引,key后面跟着euid,每个euid是24bytes长度,因此最大长度是456bytes。索引key超过对应长度则会自动截断。 ### 3.2.配置文件示例 ```json { "schema": [ { "label": "actor", "type": "VERTEX", "properties": [ { "name": "aid", "type": "STRING" }, { "name": "name", "type": "STRING" } ], "primary": "aid" }, { "label": "movie", "type": "VERTEX", "properties": [ { "name": "mid", "type": "STRING" }, { "name": "name", "type": "STRING" }, { "name": "year", "type": "INT16" }, { "name": "rate", "type": "FLOAT", "optional": true } ], "primary": "mid", "detach_property": false }, { "label": "play_in", "type": "EDGE", "properties": [{ "name": "role", "type": "STRING", "optional": true }], "constraints": [["actor", "movie"]] } ], "files": [ { "path": "actors.csv", "header": 2, "format": "CSV", "label": "actor", "columns": ["aid", "name"] }, { "path": "movies.csv", "header": 2, "format": "CSV", "label": "movie", "columns": ["mid", "name", "year", "rate"] }, { "path": "roles.csv", "header": 2, "format": "CSV", "label": "play_in", "SRC_ID": "actor", "DST_ID": "movie", "columns": ["SRC_ID", "role", "DST_ID"] } ] } ``` 对于上述配置文件,定义了三个 label:两个点类型`actor`和`movie`,一个边类型`role`。每个 label 都描述了:label 的名字、类型(点还是边)、属性字段有哪些以及每个字段的类型。对于点,另外定义了 primary 字段是哪个;对于边,另外定义了 constraints 字段,用来限制边的起点和终点只能是哪些组合。 还描述了三个数据文件,两个点的数据文件`actors.csv`和`movies.csv`,一个边的数据文件`roles.csv`。每个部分都描述了:文件的路径(path)、数据类型(format)、信息头占开头几行(header)、是哪个 label 的数据(label)、文件中每行数据中的每个列对应的字段是哪个。 对于上述配置文件,import 工具在执行的过程中会先在 TuGraph 中创建`actor`、`movie`、`role`这三个 label,然后再执行三个文件的数据导入。 ## 4.离线全量导入 离线模式只能在离线状态的服务器使用。离线导入会创建一张新图,因此更适合新安装的 TuGraph 服务器上的第一次数据导入。 要在离线模式下使用`lgraph_import`工具,可以指定`lgraph_import --online false`选项。要了解可用的命令行选项,请使用`lgraph_import --online false --help`: ```shell $ ./lgraph_import --online false -help Available command line options: --log Log file to use, empty means stderr. Default="". -v, --verbose Verbose level to use, higher means more verbose. Default=1. ... -h, --help Print this help message. Default=0. ``` 命令行参数: - **-c, --config_file** `config_file`: 导入配置文件名,其格式要求见下述。 - **--log** `log_dir`: 日志目录。默认为空字符串,此时将日志信息输出到控制台。 - **--verbose** `0/1/2`: 日志等级,等级越高输出信息越详细。默认为 1。 - **-i, --continue_on_error** `true/false`: 在碰到错误时跳过错误并继续,默认为 false,碰到错误立即退出。 - **-d, --dir** `{diretory}`: 数据库目录,导入工具会将数据写到这个目录。默认为`./db`。 - **--delimiter** `{delimiter}`: 数据文件分隔符。只在数据源是 CSV 格式时使用,默认为`","`。 - **-u, --username** `{user}`: 数据库用户名。需要是管理员用户才能执行离线导入。 - **-p, --password** `{password}`: 指定的数据库用户的密码 - **--overwrite** `true/false`: 是否覆盖数据。设为 true 时,如果数据目录已经存在,则覆盖数据。默认为`false`。 - **-g, --graph** `{graph_name}`: 指定需要导入的图种类。 - **-h, --help**: 输出帮助信息。 ### 4.1.离线导入示例 在这个例子中,我们使用上面描述的电影-演员数据来演示导入工具的使用方法。待导入数据分为三个文件:`movies.csv`,`actors.csv`,`roles.csv`。 `movies.csv`包含的是电影的信息,其中每部电影有一个 id(作为检索的 primary key),此外每部电影还拥有 title、year 和 rating 等属性。(数据来自[IMDb](http://www.imdb.com))。 ``` [movies.csv] id, name, year, rating tt0188766,King of Comedy,1999,7.3 tt0286112,Shaolin Soccer,2001,7.3 tt4701660,The Mermaid,2016,6.3 ``` 对应的 jsonline 格式如下: 也可以所有字段都是字符串形式,导入的时候会转换成对应的类型 ```json ["tt0188766","King of Comedy",1999,7.3] ["tt0286112","Shaolin Soccer",2001,7.3] ["tt4701660","The Mermaid",2016,6.3] ``` ```json ["tt0188766","King of Comedy","1999","7.3"] ["tt0286112","Shaolin Soccer","2001","7.3"] ["tt4701660","The Mermaid","2016","6.3"] ``` `actors.csv`包含的是演员的信息。每个演员也拥有一个 id,以及 name 等属性。 ``` [actors.csv] id, name nm015950,Stephen Chow nm0628806,Man-Tat Ng nm0156444,Cecilia Cheung nm2514879,Yuqi Zhang ``` > 对应的 jsonline 格式如下: ```json ["nm015950","Stephen Chow"] ["nm0628806","Man-Tat Ng"] ["nm0156444","Cecilia Cheung"] ["nm2514879","Yuqi Zhang"] ``` `roles.csv`则包含了演员在哪个电影中扮演了哪个角色的信息。其中每一行记录的是指定演员在指定电影里饰演的角色,对应数据库中的一条边。`SRC_ID` 和 `DST_ID` 分别是边的源点和目标点,他们分别是`actors.csv`和`movies.csv`中定义的`primary`属性。 ``` [roles.csv] actor, role, movie nm015950,Tianchou Yin,tt0188766 nm015950,Steel Leg,tt0286112 nm0628806,,tt0188766 nm0628806,coach,tt0286112 nm0156444,PiaoPiao Liu,tt0188766 nm2514879,Ruolan Li,tt4701660 ``` 对应的 jsonline 格式如下: ```json ["nm015950","Tianchou Yin","tt0188766"] ["nm015950","Steel Leg","tt0286112"] ["nm0628806",null,"tt0188766"] ["nm0628806","coach","tt0286112"] ["nm0156444","PiaoPiao Liu","tt0188766"] ["nm2514879","Ruolan Li","tt4701660"] ``` `配置文件import.conf`,注意每个文件中有两个标题行,因此我们需要指定`HEADER=2`选项。 ```json { "schema": [ { "label": "actor", "type": "VERTEX", "properties": [ { "name": "aid", "type": "STRING" }, { "name": "name", "type": "STRING" } ], "primary": "aid" }, { "label": "movie", "type": "VERTEX", "properties": [ { "name": "mid", "type": "STRING" }, { "name": "name", "type": "STRING" }, { "name": "year", "type": "INT16" }, { "name": "rate", "type": "FLOAT", "optional": true } ], "primary": "mid" }, { "label": "play_in", "type": "EDGE", "properties": [{ "name": "role", "type": "STRING", "optional": true }], "constraints": [["actor", "movie"]] } ], "files": [ { "path": "actors.csv", "header": 2, "format": "CSV", "label": "actor", "columns": ["aid", "name"] }, { "path": "movies.csv", "header": 2, "format": "CSV", "label": "movie", "columns": ["mid", "name", "year", "rate"] }, { "path": "roles.csv", "header": 2, "format": "CSV", "label": "play_in", "SRC_ID": "actor", "DST_ID": "movie", "columns": ["SRC_ID", "role", "DST_ID"] } ] } ``` 使用导入配置文件,我们现在可以使用以下命令导入数据: ```shell $ ./lgraph_import -c import.conf # 从import.conf读取配置信息 --dir /data/lgraph_db # 将数据存放在/data/lgraph_db --graph mygraph # 导入名为 mygraph 的图 ``` **注意**: - 如果名为`mygraph`的图已存在,导入工具将打印错误消息并退出。要强制覆盖图形,可以使用`--overwrite true` 选项。 - 配置文件和数据文件必须使用 UTF-8 编码(或普通 ASCII 编码,即 UTF-8 的子集)存储。如果任何文件使用 UTF-8 以外的编码(例如,带有 BOM 或 GBK 的 UTF-8)编码,则导入将失败,并输出分析器错误。 ## 5.在线增量导入 在线导入模式可用于将一批文件导入已在运行中的 TuGraph 实例中。这对于处理通常以固定的时间间隔进行的增量批处理更新非常便利。`lgraph_import --online true`选项使导入工具能够在线模式工作。与`离线模式`一样,在线模式有自己的命令行选项集,可以使用`-h,--help`选项进行打印输出: ```shell $ lgraph_import --online true -h Available command line options: --online Whether to import online. -h, --help Print this help message. Default=0. Available command line options: --log Log file to use, empty means stderr. Default="". -v, --verbose Verbose level to use, higher means more verbose. Default=1. -c, --config_file Config file path. -r, --url DB REST API address. -u, --username DB username. -p, --password DB password. -i, --continue_on_error When we hit a duplicate uid or missing uid, should we continue or abort. Default=0. -g, --graph The name of the graph to import into. Default=default. --skip_packages How many packages should we skip. Default=0. --delimiter Delimiter used in the CSV files --breakpoint_continue When the transmission process is interrupted,whether to re-transmit from zero package next time. Default=false -h, --help Print this help message. Default=0. ``` 文件的相关配置在配置文件中指定,其格式与`离线模式`完全相同。但是,我们现在不是将数据导入本地数据库,而是将数据发送到正在运行的 TuGraph 实例中,该实例通常运行在与运行导入工具的客户端计算机不同的计算机上。因此,我们需要指定远程计算机的 HTTP 地址的URL、DB用户和密码。 如果用户和密码有效,并且指定的图存在,导入工具将将数据发送到服务器,服务器随后解析数据并将其写入指定的图。数据将以大约 16MB 大小的包发送,在最近的换行符处中断。每个包都是以原子方式导入的,这意味着如果成功导入包,则成功导入所有数据,否则,任何数据都不会进入数据库。如果指定了`--continue_on_error true`,则忽略数据完整性错误,并忽略违规行。否则,导入将在第一个错误包处停止,并打印出已导入的包数。在这种情况下,用户可以修改数据以消除错误,然后使用`--skip_packages N`重做导入以跳过已导入的包。 ## 6.在线全量导入 在线全量导入可用于将一批文件导入运行中的TuGraph实例,TuGraph支持将两种不同类型的数据在线导入到实例中: 1. 和离线导入类型相同的原数据文件(csv等) 2. TuGraph的底层存储文件,即data.mdb文件,该文件可以由离线导入生成,也可以是其他TuGraph db的文件。 这两种方式的适用场景不同,第一种是直接将数据导入到TuGraph中,优点是一次性自动导入,操作步骤简单。但是会在server端启动一个离线导入线程, 只适合单机情况下的小规模数据导入。第二种是将已经准备好的底层存储文件导入到TuGraph中,虽然需要提前准备好mdb文件,但是对系统资源却没有很高的要求, 而且支持远程下载文件导入,非常方便,适用于高可用模式或者大规模数据的在线导入。 ### 6.1 从原数据导入 从原数据导入的执行方式是向运行中的TuGraph实例发送导入请求, 实例接到请求后先使用离线导入(V3)的方式将数据导入一个临时的db中,然后在实例中新建子图并将临时db的数据文件迁移到新子图中,最后刷新实例的元数据。 相比在线增量导入,在线全量导入的性能更高。 `lgraph_import --online true --online_type 1`选项使导入工具能够在线全量导入。 与`离线模式`一样,在线模式有自己的命令行选项集,可以使用`-h,--help`选项进行打印输出: ```shell $ lgraph_import --online true --online_type 1 -h Available command line options: --online_type The type of import online, 0 for increment, 1 for full import data,2 for full import file. Default=0. --v3 Whether to use lgraph import V3. Default=1. -h, --help Print this help message. Default=0. Available command line options: --full Whether to full import online. Default=0. -h, --help Print this help message. Default=0. Available command line options: -c, --config_file Config file path. -r, --url DB REST API address. -u, --user DB username. -p, --password DB password. -i, --continue_on_error When we hit a duplicate uid or missing uid, should we continue or abort. Default=0. -g, --graph The name of the graph to import into. Default=default. --delimiter Delimiter used in the CSV files. Default=,. --log Log dir to use, empty means stderr. Default="". -v, --verbose Verbose level to use, higher means more verbose. Default=1. --overwrite Whether to overwrite the existing DB if it already exists. Default=0. --parse_block_size Block size per parse. Default=8388608. --parse_block_threads How many threads to parse the data block. Default=5. --parse_file_threadsHow many threads to parse the files. Default=5. --generate_sst_threads How many threads to generate sst files. Default=15. --read_rocksdb_threads How many threads to read rocksdb in the final stage. Default=15. --vid_num_per_reading How many vertex data to read each time. Default=10000. --max_size_per_reading Maximum size of kvs per reading. Default=33554432. --compact Whether to compact. Default=0. --keep_vid_in_memoryWhether to keep vids in memory. Default=1. --enable_fulltext_index Whether to enable fulltext index. Default=0. --fulltext_index_analyzer fulltext index analyzer. Default=StandardAnalyzer. Possible values: {<2>: SmartChineseAnalyzer, StandardAnalyzer} -h, --help Print this help message. Default=0. ``` 文件的相关配置在配置文件中指定,其格式与`离线模式`完全相同。但是,我们现在不是将数据导入本地数据库,而是将数据导入正在运行的 TuGraph 实例中, 该实例通常运行在与运行导入工具的客户端计算机不同的计算机上。因此,我们需要指定远程计算机的 HTTP 地址的URL、DB用户和密码。 并且,配置文件(config_file参数)要求是 TuGraph 实例机器上的uri路径,其file配置也要求是 TuGraph 实例机器上资源的绝对路径。 如果用户和密码有效,导入工具将在服务器端执行在线全量导入。如果想导入的图已存在,可以使用`--overwrite true` 选项强制覆盖子图。 ### 6.2 从数据库文件导入 从原数据在线全量导入尽管操作简单、性能较高,但是对服务器资源要求较高,且耗时较长。 一种更加通用的方式是先使用离线导入在一个空db中导入子图,得到data.mdb文件,然后把该文件在线导入到 TuGraph服务中。其使用方式如下所示: ```shell $ ./lgraph_import --online true --online_type 2 -h Available command line options: --online Whether to import online. Default=0. --v3 Whether to use lgraph import V3. Default=1. -h, --help Print this help message. Default=0. Available command line options: --online_type The type of import online, 0 for increment, 1 for full import data,2 for full import file. Default=0. -h, --help Print this help message. Default=0. Available command line options: -r, --url DB REST API address. -u, --user DB username. -p, --password DB password. -g, --graph The name of the graph to import into. Default=default. --path The path of data file. --remote Whether to download file from remote server. Default=0. -h, --help Print this help message. Default=0. ``` 除普通在线导入用到的url, user和password参数之外,从数据库文件导入的在线全量导入方式 使用graph参数指定导入的子图名称,path参数指定文件路径,remote指定文件存在在远程或者本地。 如果是本地文件,则需要保证HA集群中所有的节点在path路径下都有该文件。如果是远程文件,则会先下载再导入。 需要注意的是,由于data.mdb只有一份,需要保证HA的各个节点和离线导入生成data.mdb的机器的环境完全一致, 以保证不会出现环境问题。