为大量更新声明游标的正确方法
我需要一些关于我的想法是否可行的建议。我遇到的情况是:
我需要对表的每一行进行更新。更新涉及一些逻辑。 逻辑很简单,但是需要对每一行进行操作。每行都有可能被更新。
目前,我正在考虑编写一个 ESQL/C 程序来执行此操作。我正在考虑将每一行加载到它的 相当于C结构,通过select for update游标,运行逻辑并提交。 HOLD关键字对光标起什么作用?我对这个角色有点困惑。
这些更新将在系统停机期间完成。该表包含大约 1.3 亿行。它有 约45列。大多数列的类型为 SMALLINT 和 INTEGER。
我走在正确的轨道上吗?欢迎提出建议。
数据库将是 Informix(IDS 版本 11.50 FC6)
I need some suggestions as to whether my idea is ok or not. I have a situation where:
I need to do updates to every row of a table. There is some logic involved in the updation.
The logic is very simple, but it needs to be done for every row. There is a possiblity of every row getting updated.
Currently, I'm thinking about writing an ESQL/C program to do this. I'm thinking about loading every row into its
equivalent C structure through a select for update cursor, run the logic and commit.
What role does the HOLD keyword do on the cursor? I'm bit confused about the role of this.
These updates will be done during a system downtime period. The table contains approximately 130 million rows. It has
about 45 columns. Most of the columns are of type SMALLINT and INTEGER.
Am I on the right track? Suggestions welcome.
The database will be Informix (IDS version 11.50 FC6)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
完成这项工作的关键是在服务器中完成工作,而不是让服务器选择每一行,将其传递给客户端,然后接受从客户端返回的数据。
复杂的部分可能是将工作分解为可管理的子事务;这就是“lo_val .. hi_val”条件的含义。如果您的逻辑日志足够大,可以处理所有正在更新的 1.3 亿行[大约 (2 * (行大小 + X) * 行数),我相信 X 的值约为 20],并且有空闲空间,那么您可以一次性完成所有工作。显然,这会“更新”每一行。
如果您决定必须在客户端中执行此操作(这是一个错误,但是...),那么:
您使用带有 HOLD 的 SELECT 游标,以便它在事务中保持打开状态并正确定位。您启动一项事务,获取几千行,并根据需要更新每一行。确保您使用的是准备好的 UPDATE 语句;也许您使用 WHERE CURRENT OF 条件。
不,尽管您可以在存储过程中执行此操作。这在一定程度上取决于这是否是您定期做的事情;如果是这样,也许存储过程是一个好主意,但我不会进行一次性练习。
这取决于您如何确定 lo_val 和 hi_val。我可能会使用 I4GL (因为我很熟悉它),然后我希望准备 UPDATE 语句(用问号代替“lo_val”和“hi_val”),然后我希望执行它多次,每次形成一个语句事务。因此,如果您决定使用 000000..099999、100000..199999、... 的 lo_val..hi_val 范围,那么您将进行迭代:
在 I4GL 中,您绝对不需要使用准备好的语句。如果您有 IDS 11,则可以在 SPL 中准备语句。在早期版本中,并且不会对性能造成太大影响(我怀疑您是否可以可靠地测量它),您可以简单地使用:
未经测试的代码 - 使用风险自负!
The key to making this work is to do the work in the server, rather than making the server select each row, pass it to the client, and then accept the data back from the client.
The complicated part will likely be splitting the work into manageable sub-transactions; that's what the 'lo_val .. hi_val' condition is about. If your logical logs are big enough to handle all 130 million rows being updated [about (2 * (row size + X) * number of rows), with X being a value around 20, I believe] with space to spare, then you can do it all at once. Clearly, this 'updates' every row.
If you decide you must do it in the client (a mistake, but ...), then:
You use a SELECT cursor with HOLD so that it stays open and correctly positioned across transactions. You start a transaction, fetch a few thousand rows, updating each one as needed. Make sure you are using a prepared UPDATE statement; maybe you use a WHERE CURRENT OF condition.
No, though you could do it in a stored procedure. It depends in part on whether this is something you're going to do on a regular basis; if so, maybe the stored procedure is a good idea, but I wouldn't for a one-off exercise.
It depends on how you are going to determine lo_val and hi_val. I'd probably use I4GL (because I'm fluent in it) and then I'd expect to prepare the UPDATE statement (with question marks in place of 'lo_val' and 'hi_val'), and then I'd expect to execute it a number of times, each time forming a single statement transaction. So, if you decided to go with a ranges of lo_val..hi_val from 000000..099999, 100000..199999, ... then you'd iterate:
In I4GL you would not absolutely need to use a prepared statement. If you have IDS 11, you can prepare statements in SPL. In earlier versions, and without much of a performance hit (I doubt if you could measure it reliably), you could simply use:
Untested code - use at your own risk!
SPL 是正确的选择!...但我建议您复制该表并首先测试您的批量更新。
SPL is the way to go!.. but I suggest you replicate the table and test your mass update first.