MySQL 外壳 8.0  / 第 11 章 MySQL Shell 实用程序  /  11.4 并行表导入实用程序

11.4 并行表导入实用程序

MySQL Shell 的并行表导入实用程序 util.importTable()为大型数据文件提供快速数据导入到 MySQL 关系表。该实用程序分析输入数据文件,将其分发到块中,然后使用并行连接将块上传到目标 MySQL 服务器。LOAD DATA该实用程序能够以比使用语句 的标准单线程上传快许多倍的速度完成大型数据导入。

关于实用程序

MySQL Shell 的并行表导入实用程序支持 MySQL Shell 的表导出实用程序的输出,它可以压缩它作为输出生成的数据文件,并可以将其导出到本地文件夹或对象存储桶。并行表导入实用程序的默认方言是表导出实用程序生成的输出文件的默认方言。并行表导入实用程序也可用于从其他来源上传文件。

要导入的一个或多个数据文件可以位于以下任何位置:

  • 客户端主机可作为本地磁盘访问的位置。

  • 客户端主机可通过 HTTP 或 HTTPS 访问的远程位置,用 URL 指定。以这种方式访问​​的文件不支持模式匹配。

  • Oracle Cloud Infrastructure 对象存储桶(来自 MySQL Shell 8.0.21)。

数据被导入到活动 MySQL 会话所连接的 MySQL 服务器中的单个关系表中。

当您运行并行表导入实用程序时,您指定一个或多个数据文件中的字段与 MySQL 表中的列之间的映射。您可以为LOAD DATA 语句设置字段和行处理选项,以处理任意格式的数据文件。对于多个文件,所有文件的格式必须相同。该实用程序的默认方言映射到使用 SELECT...INTO OUTFILE语句与该语句的默认设置。该实用程序还具有映射到 CSV 文件(在 DOS 或 UNIX 系统上创建)、TSV 文件和 JSON 的标准数据格式的预设方言,您可以根据需要使用字段和行处理选项自定义这些。请注意,JSON 数据必须采用每行文档格式。

自推出以来,并行表导入实用程序已添加了许多功能,因此请使用最新版本的 MySQL Shell 来获得该实用程序的全部功能。

输入预处理

从 MySQL Shell 8.0.22 开始,并行表导入实用程序可以从数据文件或文件中捕获列以进行输入预处理,其方式与 LOAD DATA语句相同。可以丢弃所选数据,或者您可以转换数据并将其分配给目标表中的列。

Oracle 云基础设施对象存储导入

直到 MySQL Shell 8.0.20,数据必须从客户端主机可访问的位置作为本地磁盘导入。从 MySQL Shell 8.0.21 开始,数据也可以从 osBucketName选项指定的 Oracle Cloud Infrastructure 对象存储桶中导入。

多数据文件导入

在 MySQL Shell 8.0.22 之前,并行表导入实用程序可以将单个输入数据文件导入单个关系表。从 MySQL Shell 8.0.23 开始,该实用程序还能够导入指定的文件列表,并且支持通配符模式匹配以包含来自某个位置的所有相关文件。单次运行该实用程序上传的多个文件被放入一个关系表中,因此,例如,从多个主机导出的数据可以合并到一个表中以用于分析。

压缩文件处理

在 MySQL Shell 8.0.21 之前,并行表导入实用程序只接受未压缩的输入数据文件。该实用程序分析数据文件,将其分成块,并将块上传到目标 MySQL 服务器中的关系表,在并行连接之间划分块。从 MySQL Shell 8.0.22 开始,该实用程序还可以接受压缩在 gzip( .gz) 和 zstd (.zst)格式,根据文件扩展名自动检测格式。该实用程序以压缩格式从存储中上传压缩文件,从而为该部分传输节省带宽。压缩文件无法分块分发,因此该实用程序使用其并行连接来解压缩多个文件并将其同时上传到目标服务器。如果只有一个输入数据文件,压缩文件的上传只能使用一个连接。

MySQL Shell 的转储加载实用程序 util.loadDump()旨在导入由 MySQL Shell 的实例转储实用程序 util.dumpInstance()、模式转储实用程序 util.dumpSchemas()和表转储实用程序 生成的分块输出文件和元数据的组合util.dumpTables(). 如果要在将分块输出文件上载到目标服务器之前修改任何数据,可以将并行表导入实用程序与转储加载实用程序结合使用。为此,首先使用转储加载实用程序只加载所选表的 DDL,以在目标服务器上创建表。然后使用并行表导入实用程序从表的输出文件中捕获和转换数据,并将其导入到目标表中。根据需要对要修改数据的任何其他表重复该过程。最后,使用转储加载实用程序加载您不想修改的任何剩余表的 DDL 和数据,不包括您修改过的表。 修改转储数据

要求和限制

并行表导入实用程序使用LOAD DATA LOCAL INFILE语句上传数据,因此 local_infile必须ON在目标服务器上设置系统变量。在运行并行表导入实用程序之前,您可以通过在 SQL 模式下发出以下语句来执行此操作:

SET GLOBAL local_infile = 1;

为避免已知的潜在安全问题LOAD DATA LOCAL,当 MySQL 服务器LOAD DATA 使用文件传输请求回复并行表导入实用程序的请求时,该实用程序仅发送预定的数据块,而忽略服务器尝试的任何特定请求。有关详细信息,请参阅 LOAD DATA LOCAL 的安全注意事项

运行实用程序

并行表导入实用程序需要一个现有的经典 MySQL 协议连接到目标 MySQL 服务器。每个线程都打开自己的会话,将数据块发送到 MySQL 服务器,或者在压缩文件的情况下,并行发送多个文件。您可以调整线程数、每个块中发送的字节数以及每个线程的最大数据传输速率,以平衡网络负载和数据传输速度。该实用程序无法在不支持LOAD DATA语句的 X 协议连接上运行。

在 MySQL Shell API 中,并行表导入实用程序是util全局对象的一个​​函数,具有以下签名:

importTable ({file_name | file_list}, options)

options是导入选项的字典,如果为空则可以省略。这些选项在本主题的最后一节中列出。

file_name是一个字符串,指定包含要导入的数据的单个文件的名称和路径。或者,file_list是指定多个数据文件的文件路径数组。在 Windows 上,反斜杠必须在文件路径中转义,或者您可以改用正斜杠。

  • 对于本地磁盘上客户端主机可访问的文件,您可以在目录路径前加上 file://模式前缀,或允许它默认为该模式。对于以这种方式访问​​的文件,文件路径可以包含用于模式匹配的通配符*(多个字符)和 (单个字符)。?请注意,如果这些通配符出现在文件路径中,该实用程序会将它们视为通配符,因此可能会尝试使用不正确的文件传输策略。

  • http://对于客户端主机可通过 HTTP或 HTTPS 访问的文件,请https://http[s]://host.domain[:port]/path. 对于以这种方式访问​​的文件,模式匹配不可用。HTTP 服务器必须支持 Range 请求头,并且必须向客户端返回 Content-Range 响应头。

  • 对于 Oracle Cloud Infrastructure 对象存储桶中的文件,指定桶中文件的路径,并使用osBucketName选项指定桶名称。

该函数返回 void,或在出现错误时返回异常。如果导入被用户使用 Ctrl+C中途停止或因错误而停止,该实用程序将停止发送数据。当服务器处理完它收到的数据时,会返回消息,显示当时每个线程正在导入的块、完成百分比以及目标表中更新的记录数。

下面的示例,第一个在 MySQL Shell 的 JavaScript 模式中,第二个在 MySQL Shell 的 Python 模式中,将单个 CSV 文件 /tmp/productrange.csv中的数据导入数据库中的 productsmydb ,跳过文件中的标题行:

mysql-js> util.importTable("/tmp/productrange.csv", {schema: "mydb", table: "products", dialect: "csv-unix", skipRows: 1, showProgress: true})
mysql-py> util.import_table("/tmp/productrange.csv", {"schema": "mydb", "table": "products", "dialect": "csv-unix", "skipRows": 1, "showProgress": True})

MySQL Shell 的 Python 模式下的以下示例仅指定 CSV 文件的方言。mydb 是 MySQL Shell 会话的活动模式。因此,该实用程序将文件中的数据导入到数据库中 /tmp/productrange.csvproductrange表中 mydb

mysql-py> \use mydb
mysql-py> util.import_table("/tmp/productrange.csv", {"dialect": "csv-unix"})

MySQL Shell 的 Python 模式下的以下示例从多个文件导入数据,包括单独命名的文件、使用通配符模式匹配指定的文件范围和压缩文件的混合:

mysql-py> util.import_table(
    [
        "data_a.csv",
        "data_b*",
        "data_c*",
        "data_d.tsv.zst",
        "data_e.tsv.zst",
        "data_f.tsv.gz",
        "/backup/replica3/2021_01_12/data_g.tsv",
        "/backup/replica3/2021_01_13/*.tsv",
    ],
    {"schema": "mydb", "table": "productrange"}
)

还可以使用mysqlsh命令界面从命令行调用并行表导入实用程序。使用此接口,您可以调用该实用程序,如以下示例所示:

mysqlsh mysql://root:@127.0.0.1:3366 --ssl-mode=DISABLED -- util import-table /r/mytable.dump --schema=mydb --table=regions --bytes-per-chunk=10M --linesTerminatedBy=$'\r\n'

当您导入多个数据文件时,如果使用通配符模式匹配指定的文件范围被引用,则由 MySQL Shell 的 glob 模式匹配逻辑扩展,如下例所示。否则,它们会被您输入 mysqlsh命令的用户 shell 的模式匹配逻辑扩展。

mysqlsh mysql://root:@127.0.0.1:3366 -- util import-table data_a.csv "data_b*" data_d.tsv.zst --schema=mydb --table=productrange --osBucketName=mybucket

当您使用mysqlsh命令的 API 参考参数直接调用并行表导入实用程序(破折号-破折号-空格序列“ -- ”)时,在 MySQL Shell 8.0.24 之前,columns 不支持该选项,因为不接受数组值,因此数据文件中的输入行必须包含目标表中每一列的匹配字段。从 MySQL Shell 8.0.24 开始,支持该选项,您可以使用字典参数指定列。另请注意,如上例所示,在支持此功能的 shell 中(例如bashkshmkshzsh). 有关 mysqlsh命令行集成的信息,请参阅 第 5.8 节,“API 命令行集成”

导入表的选项

并行表导入实用程序可以使用以下导入选项来指定数据的导入方式:

schema: "db_name"

连接的 MySQL 服务器上的目标数据库的名称。如果省略此选项,实用程序将尝试识别和使用当前 MySQL Shell 会话使用的模式名称,如连接 URI 字符串、\use命令或 MySQL Shell 选项中指定的那样。如果未指定架构名称且无法从会话中识别,则返回错误。

table: "table_name"

目标关系表的名称。如果省略此选项,该实用程序假定表名是不带扩展名的数据文件的名称。目标表必须存在于目标数据库中。

columns: array of column names

包含来自一个或多个导入文件的列名的字符串数组,按照它们映射到目标关系表中的列的顺序给出。如果导入的数据不包含目标表的所有列,或者导入数据中字段的顺序与表中列的顺序不同,请使用此选项。如果省略此选项,则输入行应包含目标表中每一列的匹配字段。

从 MySQL Shell 8.0.22 开始,您可以使用此选项从一个或多个导入文件中捕获列以进行输入预处理,其方式与 LOAD DATA语句相同。当您使用整数值代替数组中的列名时,导入文件中的该列将被捕获为用户变量 ,例如。可以丢弃所选数据,也可以使用 选项转换数据并将其分配给目标表中的列。 @int@1decodeColumns

在此示例中,在 MySQL Shell 的 JavaScript 模式下,导入文件中的第二列和第四列被分配给用户变量@1@2,并且没有 decodeColumns选项将它们分配给目标表中的任何列,因此它们被丢弃。

mysql-js> util.importTable('file.txt', {
            table: 't1',
            columns: ['column1', 1, 'column2', 2, 'column3']
          });
decodeColumns: dictionary

键值对的字典,将通过选项捕获的导入文件列分配给 目标表中的列,并以与语句的子句columns相同的方式为其指定预处理转换。此选项可从 MySQL Shell 8.0.22 获得。 SETLOAD DATA

在 MySQL Shell 的 JavaScript 模式下的这个示例中,数据文件中的第一个输入列用作目标表中的第一列。第二个输入列,@1通过columns选项赋值给变量,经过除法运算后,作为目标表中第二列的值。

mysql-js> util.importTable('file.txt', {
            columns: ['column1', 1],
            decodeColumns: {'column2': '@1 / 100'}
          });

在 MySQL Shell 的 JavaScript 模式下的这个例子中,数据文件中的输入列都被分配给变量,然后以各种方式转换并用于填充目标表的列:

mysql-js> util.importTable('file.txt', {
            table: 't1',
            columns: [1, 2],
            decodeColumns: {
              'a': '@1',
              'b': '@2',
              'sum': '@1 + @2',
              'multiple': '@1 * @2',
              'power': 'POW(@1, @2)'
            }
          });
skipRows: number

在导入文件的开头跳过此行数的数据,或者在多个导入文件的情况下,在文件列表中包含的每个文件的开头。您可以使用此选项在上传到表时省略包含列名称的初始标题行。默认是不跳过任何行。

replaceDuplicates: [true|false]

是否应替换 ( true) 或跳过 ( false) 与现有行具有相同主键或唯一索引值的输入行。默认值为 false

dialect: [default|csv|csv-unix|tsv|json]

使用一组适合指定文件格式的字段和行处理选项。您可以使用所选方言作为进一步自定义的基础,方法是指定 、 、 、 和 选项中的一个或 linesTerminatedBy多个 fieldsTerminatedByfieldsEnclosedBy更改 fieldsOptionallyEnclosed设置 fieldsEscapedBy。默认方言映射到使用创建的文件 SELECT...INTO OUTFILE语句与该语句的默认设置。这是 MySQL Shell 的表导出实用程序生成的输出文件的默认值。其他方言适用于 CSV 文件(在 DOS 或 UNIX 系统上创建)、TSV 文件和 JSON 数据。适用于每种方言的设置如下:

表 11.2 并行表导入实用程序的方言设置

dialect

linesTerminatedBy

fieldsTerminatedBy

fieldsEnclosedBy

fieldsOptionallyEnclosed

fieldsEscapedBy

default

[如果]

[标签]

[空的]

false

\

csv

[CR][低频]

,

''

true

\

csv-unix

[如果]

,

''

false

\

tsv

[CR][低频]

[标签]

''

true

\

json

[如果]

[如果]

[空的]

false

[空的]


笔记
  1. 方言的回车和换行值与操作系统无关。

  2. 如果您使用linesTerminatedByfieldsTerminatedByfieldsEnclosedByfieldsOptionallyEnclosedfieldsEscapedBy选项,根据命令解释器的转义约定,如果您在选项值中使用反斜杠字符 (\),则可能需要加倍。

  3. 与带有该 LOAD DATA语句的 MySQL 服务器一样,MySQL Shell 不会验证您指定的字段和行处理选项。这些选项的不准确选择会导​​致数据被部分地和/或错误地导入到错误的字段中。始终在开始导入之前验证您的设置,然后再验证结果。

linesTerminatedBy: "characters"

终止输入数据文件中每一行的一个或多个字符(或空字符串)。\n默认值与指定的方言相同,如果省略方言选项,则为换行符 ( )。此选项等同于 语句的LINES TERMINATED BY选项 。请注意,该实用程序不为语句的选项 LOAD DATA提供等效 项,该选项设置为空字符串。 LINES STARTING BYLOAD DATA

fieldsTerminatedBy: "characters"

终止输入数据文件中每个字段的一个或多个字符(或空字符串)。默认值与指定的方言相同,\t如果省略方言选项,则为制表符 ( )。此选项等同于 语句 的FIELDS TERMINATED BY选项 。LOAD DATA

fieldsEnclosedBy: "character"

包含输入数据文件或文件中每个字段的单个字符(或空字符串)。默认值与指定的方言相同,如果省略方言选项,则为空字符串。此选项等同于语句 的FIELDS ENCLOSED BY选项。LOAD DATA

fieldsOptionallyEnclosed: [ true | false ]

给定的字符是 fieldsEnclosedBy包含一个或多个输入数据文件中的所有字段 ( false),还是仅在某些情况下包含字段 ( true)。默认为指定的方言,或者false方言选项被省略。此选项使该 fieldsEnclosedBy选项等同于 语句 的FIELDS OPTIONALLY ENCLOSED BY 选项。LOAD DATA

fieldsEscapedBy: "character"

在一个或多个输入数据文件中开始转义序列的字符。如果未提供,则不会进行转义序列解释。默认值与指定的方言相同,如果省略方言选项,则为反斜杠 (\)。此选项等同于语句 的FIELDS ESCAPED BY选项 。LOAD DATA

characterSet: "charset"

在 MySQL Shell 8.0.21 中添加。此选项指定一种字符集编码,在导入过程中使用该编码解释输入数据。将选项设置为 binary意味着在导入期间不进行任何转换。当您省略此选项时,导入使用 character_set_database 系统变量指定的字符集来解释输入数据。

bytesPerChunk: "size"

对于多个输入数据文件的列表,此选项不可用。对于单个输入数据文件,此选项指定线程为每次LOAD DATA调用目标服务器发送的字节数(加上到达行末所需的任何额外字节)。该实用程序将数据分发到此大小的块中,供线程拾取并发送到目标服务器。块大小可以指定为字节数,或使用后缀 k(千字节)、M(兆字节)、G(千兆字节)。例如, bytesPerChunk="2k"使线程发送大约 2 KB 的块。最小块大小为 131072 字节,默认块大小为 50M。

threads: number

用于将输入文件中的数据发送到目标服务器的最大并行线程数。如果您未指定线程数,则默认最大值为 8。对于多个输入数据文件的列表,该实用程序会创建指定或最大线程数。对于单个输入数据文件,该实用程序使用以下公式计算要创建的线程的适当数量,直至达到此最大值:

min{max{1, threads}, chunks}}

其中threads是最大线程chunks数, 是数据将被拆分成的 chunk 数,计算方法是将文件大小除以 bytesPerChunk大小然后加 1。计算确保如果最大线程数超过 number实际发送的块的数量,该实用程序不会创建不必要的线程。

压缩文件无法分块分发,因此该实用程序使用其并行连接一次上传多个文件。如果只有一个输入数据文件,压缩文件的上传只能使用一个连接。

maxRate: "rate"

每个线程每秒字节数的最大数据吞吐量限制。如果您需要避免使客户端主机或目标服务器的网络或 I/O 或 CPU 饱和,请使用此选项。最大速率可以指定为字节数,或使用后缀 k(千字节)、M(兆字节)、G(千兆字节)。例如, maxRate="5M"将每个线程限制为每秒 5MB 的数据,对于八个线程,传输速率为 40MB/秒。默认值为 0,表示没有限制。

showProgress: [ true | false ]

显示 ( true) 或隐藏 ( false) 导入进度信息。默认是true如果 stdout 是终端 (tty),false 否则。

sessionInitSql: list of strings

在每个客户端会话开始时运行的 SQL 语句列表,用于将数据加载到目标 MySQL 实例中。您可以使用此选项更改会话变量。此选项可从 MySQL Shell 8.0.30 获得。例如,以下语句针对实用程序在导入过程中使用的会话跳过目标 MySQL 实例上的二进制日志记录,并增加可用于创建索引的线程数:

sessionInitSQL: ["SET SESSION sql_log_bin=0;", "SET SESSION innodb_ddl_threads=8,"]

如果在运行 SQL 语句时发生错误,导入将停止并返回一条错误消息。

Oracle 云基础设施选项

MySQL Shell 支持导入存储在 Oracle Cloud Infrastructure 对象存储桶中的输入数据文件。

osBucketName: "string"

在 MySQL Shell 8.0.21 中添加。输入数据文件所在的 Oracle Cloud Infrastructure 对象存储桶的名称。默认情况下, [DEFAULT]位于 的 Oracle Cloud Infrastructure CLI 配置文件中的配置文件 ~/.oci/config用于建立与存储桶的连接。ociConfigFile您可以使用和 ociProfile选项替换要用于连接的替代配置文件 。有关设置 CLI 配置文件的说明,请参阅 SDK 和 CLI 配置文件

osNamespace: "string"

在 MySQL Shell 8.0.21 中添加。by 命名的对象存储桶所在的 Oracle Cloud Infrastructure 命名空间osBucketName。对象存储桶的命名空间显示在 Oracle Cloud Infrastructure 控制台中桶详细信息页面的 Bucket Information 选项卡中,或者可以使用 Oracle Cloud Infrastructure 命令行界面获取。

ociConfigFile: "string"

在 MySQL Shell 8.0.21 中添加。一个 Oracle Cloud Infrastructure CLI 配置文件,其中包含用于连接的配置文件,而不是默认位置中的配置文件~/.oci/config

ociProfile: "string"

在 MySQL Shell 8.0.21 中添加。用于连接的 Oracle Cloud Infrastructure 配置文件的配置文件名称,而不是用于连接[DEFAULT] 的 Oracle Cloud Infrastructure CLI 配置文件中的配置文件。

S3 兼容服务的选项

MySQL Shell 支持导入存储在 S3 兼容存储桶中的输入数据文件,例如 Amazon Web Services (AWS) S3。

有关支持的服务及其配置要求的信息,请参阅 第 4.7 节“云服务配置”

s3BucketName: "string"

在 MySQL Shell 8.0.30 中添加。转储文件所在的 S3 存储桶的名称。默认情况下, defaultAmazon Web Services (AWS) CLI 中的配置文件configcredentials位于的文件 ~/.aws/用于建立与 S3 存储桶的连接。s3ConfigFile您可以使用和 s3CredentialsFile选项替换连接的替代配置和凭据。有关安装和配置 AWS CLI 的说明,请参阅 AWS CLI 入门

s3CredentialsFile: "string"

在 MySQL Shell 8.0.30 中添加。包含用于连接的用户凭据的凭据文件,而不是默认位置中的凭据, ~/.aws/credentials. 通常,凭据文件包含 用于连接 的aws_access_key_id和 。aws_secret_access_key

s3ConfigFile: "string"

在 MySQL Shell 8.0.30 中添加。一个 AWS CLI 配置文件,其中包含用于连接的配置文件,而不是默认位置中的配置文件 ~/.aws/config。通常,配置文件包含用于连接的区域和输出类型。

s3Profile: "string"

在 MySQL Shell 8.0.30 中添加。用于连接的 s3 CLI 配置文件的配置文件名称,而不是用于连接 default的 AWS CLI 配置文件中的配置文件。

s3EndpointOverride: "string"

要使用的端点的 URL 而不是默认值。

在 MySQL Shell 8.0.30 中添加。连接到 Oracle Cloud Infrastructure S3 兼容性 API 时,端点采用以下格式: . 替换为对象存储命名空间和 您的区域标识符。例如,美国东部(阿什本)区域的区域标识符是。 https://namespace.compat.objectstorage.region.oraclecloud.comnamespaceregionus-ashburn-1

对于美国东部(阿什本)区域中名为 axaxnpcrorw5 的命名空间:

https://axaxnpcrorw5.compat.objectstorage.us-ashburn-1.oraclecloud.com.