如何提高 mysql LOAD XML LOCAL INFILE table 导入的性能?
How to improve performance of a mysql LOAD XML LOCAL INFILE table import?
对于 mysql 数据库,我有一些 XML 转储文件。
table pricing
table 的导入文件如下所示:
<database>
<table>
<row>
<id>5954017</id>
<foo>narf</foo>
<bar_id>1377</bar_id>
<price_single>800.00</price_single>
<price_double>1500.00</price_double>
<price_triple>2000.00</price_triple>
<price_quad>1900.00</price_quad>
<currency>USD</currency>
</row>
...
</table>
</database>
它有
$ xmllint --xpath "count(//row)" import.xml
223198
行,其大小为:
du -h import.xml
69M import.xml
我想通过 mysql 的 LOAD XML
功能导入。 table 将始终被预先截断。
MySQL [my_database]> LOAD XML LOCAL INFILE 'import.xml' INTO TABLE pricing ROWS IDENTIFIED BY '<row>' \G
成功了,但是table import 貌似耗时比较长:
Query OK, 223198 rows affected (1 hour 44 min 48.40 sec)
Records: 223198 Deleted: 0 Skipped: 0 Warnings: 0
我读到人们正在使用此 LOAD INFILE 功能导入千兆字节的数据,我预计它的性能会快得多,在几分钟内,而不是几小时内。我的期望错了吗?对于这样一个包含 200,000 个条目的数据集,这是正常时间吗?
(我还将此速度与自定义 php 导入脚本进行比较,该脚本手动解析 XML 并逐行插入每一行;并且该任务需要 45 分钟来完成所有 tables。我希望 LOAD XML LOCAL INFILE
能够胜过该任务。)
我的 table 看起来像这样:
MySQL [my_database]> DESCRIBE pricing;
+----------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------------+--------------+------+-----+---------+-------+
| id | int(11) | NO | PRI | NULL | |
| foo | varchar(256) | YES | | NULL | |
| bar_id | int(11) | YES | | NULL | |
| price_single | float | YES | | NULL | |
| price_double | float | YES | | NULL | |
| price_triple | float | YES | | NULL | |
| price_quad | float | YES | | NULL | |
| currency | varchar(3) | YES | | NULL | |
+----------------+--------------+------+-----+---------+-------+
创建于:
DROP TABLE IF EXISTS `pricing`;
CREATE TABLE `pricing` (
`id` int(11) NOT NULL,
`foo` varchar(256) DEFAULT NULL,
`bar_id` int(11) DEFAULT NULL,
`price_single` float DEFAULT NULL,
`price_double` float DEFAULT NULL,
`price_triple` float DEFAULT NULL,
`price_quad` float DEFAULT NULL,
`currency` varchar(3) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
我可以做些什么来提高 LOAD XML LOCAL INFILE
的性能?
将您的 XML 转换为 CSV 文件,几乎可以即时导入。
您可以通过 xslt 转换 XML,例如使用xsltproc
:
$ xsltproc transformToCsv.xsl price.xml > price.csv
"5954017"╡"narf"╡"1377"╡"800.00"╡"1500.00"╡"2000.00"╡"1900.00"╡"USD"
合适的 xslt transformToCsv.xsl
看起来像这样:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"
encoding="utf-8"/>
<xsl:param name="delim"
select="'╡'"/>
<xsl:param name="quote"
select="'"'"/>
<xsl:param name="break"
select="' '"/>
<xsl:template match="/">
<xsl:apply-templates select="database/table/row"/>
</xsl:template>
<xsl:template match="row">
<xsl:apply-templates/>
<xsl:if test="following-sibling::*">
<xsl:value-of select="$break"/>
</xsl:if>
</xsl:template>
<xsl:template match="*">
<xsl:value-of select="concat($quote, normalize-space(), $quote)"/>
<xsl:if test="following-sibling::*">
<xsl:value-of select="$delim"/>
</xsl:if>
</xsl:template>
<xsl:template match="text()"/>
</xsl:stylesheet>
然后导入语法更改为:
$ mysql \
-h YOUR_MYSQL_HOST \
-P YOUR_PORT \
-uYOUR_USER \
-pYOUR_PASSWORD \
YOUR_DATABASE \
-e "LOAD DATA LOCAL INFILE 'pricing.csv' INTO TABLE pricing FIELDS TERMINATED BY '╡' ENCLOSED BY '\"' \G"
导入 200,000 个条目成为(毫秒)秒的事情。
对于 mysql 数据库,我有一些 XML 转储文件。
table pricing
table 的导入文件如下所示:
<database>
<table>
<row>
<id>5954017</id>
<foo>narf</foo>
<bar_id>1377</bar_id>
<price_single>800.00</price_single>
<price_double>1500.00</price_double>
<price_triple>2000.00</price_triple>
<price_quad>1900.00</price_quad>
<currency>USD</currency>
</row>
...
</table>
</database>
它有
$ xmllint --xpath "count(//row)" import.xml
223198
行,其大小为:
du -h import.xml
69M import.xml
我想通过 mysql 的 LOAD XML
功能导入。 table 将始终被预先截断。
MySQL [my_database]> LOAD XML LOCAL INFILE 'import.xml' INTO TABLE pricing ROWS IDENTIFIED BY '<row>' \G
成功了,但是table import 貌似耗时比较长:
Query OK, 223198 rows affected (1 hour 44 min 48.40 sec)
Records: 223198 Deleted: 0 Skipped: 0 Warnings: 0
我读到人们正在使用此 LOAD INFILE 功能导入千兆字节的数据,我预计它的性能会快得多,在几分钟内,而不是几小时内。我的期望错了吗?对于这样一个包含 200,000 个条目的数据集,这是正常时间吗?
(我还将此速度与自定义 php 导入脚本进行比较,该脚本手动解析 XML 并逐行插入每一行;并且该任务需要 45 分钟来完成所有 tables。我希望 LOAD XML LOCAL INFILE
能够胜过该任务。)
我的 table 看起来像这样:
MySQL [my_database]> DESCRIBE pricing;
+----------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------------+--------------+------+-----+---------+-------+
| id | int(11) | NO | PRI | NULL | |
| foo | varchar(256) | YES | | NULL | |
| bar_id | int(11) | YES | | NULL | |
| price_single | float | YES | | NULL | |
| price_double | float | YES | | NULL | |
| price_triple | float | YES | | NULL | |
| price_quad | float | YES | | NULL | |
| currency | varchar(3) | YES | | NULL | |
+----------------+--------------+------+-----+---------+-------+
创建于:
DROP TABLE IF EXISTS `pricing`;
CREATE TABLE `pricing` (
`id` int(11) NOT NULL,
`foo` varchar(256) DEFAULT NULL,
`bar_id` int(11) DEFAULT NULL,
`price_single` float DEFAULT NULL,
`price_double` float DEFAULT NULL,
`price_triple` float DEFAULT NULL,
`price_quad` float DEFAULT NULL,
`currency` varchar(3) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
我可以做些什么来提高 LOAD XML LOCAL INFILE
的性能?
将您的 XML 转换为 CSV 文件,几乎可以即时导入。
您可以通过 xslt 转换 XML,例如使用xsltproc
:
$ xsltproc transformToCsv.xsl price.xml > price.csv
"5954017"╡"narf"╡"1377"╡"800.00"╡"1500.00"╡"2000.00"╡"1900.00"╡"USD"
合适的 xslt transformToCsv.xsl
看起来像这样:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"
encoding="utf-8"/>
<xsl:param name="delim"
select="'╡'"/>
<xsl:param name="quote"
select="'"'"/>
<xsl:param name="break"
select="' '"/>
<xsl:template match="/">
<xsl:apply-templates select="database/table/row"/>
</xsl:template>
<xsl:template match="row">
<xsl:apply-templates/>
<xsl:if test="following-sibling::*">
<xsl:value-of select="$break"/>
</xsl:if>
</xsl:template>
<xsl:template match="*">
<xsl:value-of select="concat($quote, normalize-space(), $quote)"/>
<xsl:if test="following-sibling::*">
<xsl:value-of select="$delim"/>
</xsl:if>
</xsl:template>
<xsl:template match="text()"/>
</xsl:stylesheet>
然后导入语法更改为:
$ mysql \
-h YOUR_MYSQL_HOST \
-P YOUR_PORT \
-uYOUR_USER \
-pYOUR_PASSWORD \
YOUR_DATABASE \
-e "LOAD DATA LOCAL INFILE 'pricing.csv' INTO TABLE pricing FIELDS TERMINATED BY '╡' ENCLOSED BY '\"' \G"
导入 200,000 个条目成为(毫秒)秒的事情。