【问题标题】:Performance tuning my update statement性能调整我的更新语句
【发布时间】:2014-05-26 19:06:48
【问题描述】:

您好,我必须每晚更新我数据库中的数量,至少需要 200 万个零件。我使用 jdbc 作为我的 mysql 连接器。

我只使用一张仓库表。

我们每晚都会从每个仓库收到一份文件,其中包含需要更新的部件号和数量。

这是仓库架构:

warehouse | CREATE TABLE `warehouse` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`sap_article_id` varchar(128) NOT NULL,
`sap_warehouse` varchar(24) NOT NULL,
 `as400_warehouse` varchar(10) NOT NULL,
 `ds_warehouse` varchar(10) NOT NULL,
  `atp_qty` int(11) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `article` (`sap_article_id`)
 ) ENGINE=MyISAM AUTO_INCREMENT=497524962 DEFAULT CHARSET=latin1 |

仓库索引:

+-----------+------------+----------+--------------+----------------+-----------+-------------+----------+--------+------+------------+---------+
| Table     | Non_unique | Key_name | Seq_in_index | Column_name    | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+-----------+------------+----------+--------------+----------------+-----------+-------------+----------+--------+------+------------+---------+
| warehouse |          0 | PRIMARY  |            1 | id             | A         |     2858699 |     NULL | NULL   |      | BTREE      |         |
| warehouse |          1 | article  |            1 | sap_article_id | A         |      571739 |     NULL | NULL   |      | BTREE      |         |
+-----------+------------+----------+--------------+----------------+-----------+-------------+----------+--------+------+------------+---------+

仓库表中大约有 300 万条记录。

我无法在夜间完成所有这些文件的处理。

这是我的逻辑......就像我说我有多个文件需要为每个仓库处理一个。

"SELECT sap_article_id FROM " + WAREHOUSE_TABLE
                                + " WHERE " + "sap_article_id='" + sapArticleId
                                + "' AND sap_warehouse='" + sapWarehouse + "'";

如果仓库中有零件...

我们更新它..

  "UPDATE " + WAREHOUSE_TABLE + " "
                                    + "SET ds_warehouse='0'," + "atp_qty=" + atpQty
                                    + " WHERE sap_article_id='" + sapArticleId + "' AND "
                                    + "sap_warehouse='" + sapWarehouse + "'"; 

如果它不存在,我们插入它...

"INSERT INTO " + WAREHOUSE_TABLE + "("
                            + "sap_article_id,sap_warehouse,as400_warehouse,ds_warehouse,atp_qty"
                            + ") VALUES ('"+sapArticleId+"'," + "'" + sapWarehouse
                            + "'," + "'" + as400Warehouse + "'," + "'0'," + "'"
                            + atpQty + "'" + ")";

然后我们移动到文件中的下一行并重复。

我做错了什么或者我可以做些什么来大大提高这个过程的速度。就像我之前所说的那样,这需要的时间太长了,我无法在给定的时间内完成我的任务。我有大约 3-5 小时的时间来处理所有这些数据,而现在需要 12 多个小时。

【问题讨论】:

  • 查看插入...更新重复键
  • 您如何处理交易?如果您在同一事务中全部(或在块中)进行大规模更新,通常会更快。另一件事......而不是为每条记录构建 SQL 语句,您最好准备两个参数化 SQL 语句(一个用于更新,一个用于插入),然后使用正确的参数值多次执行它们。跨度>
  • @Frazz 我不明白你在说准备两个参数化 SQL 语句时在说什么。你能给我一个例子吗?
  • 实际上不在 java 中。无论如何,像 UPDATE warehouse_table SET ds_warehouse='0', atp_qty=:apt_qty WHERE sap_article_id=:sap_article_id AND sap_warehouse=:sap_warehouse... 这个查询有 3 个参数。您准备一次,然后您可以执行数百万次更改参数。问题是,当您准备它时,服务器会对其进行分析并决定如何执行它。参数的值对分析并不重要。如果你不准备它,那么你执行的每一个查询都会在执行前被服务器单独分析......这不好。
  • @Frazz 你是说我没有准备?这是相同的查询,只是每次都更改参数......如果我不准备它,我该如何准备它。

标签: java mysql sql optimization sql-update


【解决方案1】:

听起来你正在做这个 RBAR,这是我通常尝试避免的,就像瘟疫一样。而是尝试像下面那样进行基于集合的更新,然后(如果必须)为各个数据库执行循环:

MERGE INTO tablename USING table_reference ON (condition)
   WHEN MATCHED THEN
   UPDATE SET column1 = value1 [, column2 = value2 ...]
   WHEN NOT MATCHED THEN
   INSERT (column1 [, column2 ...]) VALUES (value1 [, value2 ...

【讨论】:

  • 适用于 Microsoft SQL、Oracle 数据库、DB2、Teradata、EXASOL 和 MS SQL。请参阅:en.wikipedia.org/wiki/Upsert。我个人在 MSSQL 中使用过。
  • 附加的 Wiki 文章指的是 MySQL 中非标准但有效的合并实现(在标题下 - 其他非标准实现)。
猜你喜欢
  • 2015-07-27
  • 1970-01-01
  • 2017-08-29
  • 1970-01-01
  • 2021-04-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多