注册 登录
编程论坛 VFP论坛

需频繁遍历更新的字段,是否有必要创建索引?

cssnet 发布于 7 天前 13:18, 427 次点击
问题:
表 mytable 有10000行记录,其中有一个整型值字段 Score,会在每一次循环中,遍历更新一次,并查询是否存在值大于95的记录:

select B
use myTable
select A
use myIndex

scan
   *select A
   lnPara = A.ParaIndex
   select B
   * 批量更新所有记录
   update mytable set score = setNewScore(lnPara)
   locate for score > 95
   if found()
      do something
   endif
endscan

Score 字段是否有必要建立索引,以便 locate for score > 95 能快速查询?
存在这个疑问是因为:
update mytable set score = setNewScore(lnPara)
会遍历更新10000次score,同时VFP要自动维护score的索引,这造成性能损失。
两相权衡之下,究竟是建立索引效率高,还是不要索引更快?

DeepSeek 回答:
在你的当前代码逻辑下,不建议为score字段建立索引,原因如下:
索引维护成本:每次UPDATE都会导致score索引的完全重建(10000次更新)
查找频率低:每次循环只执行1次LOCATE
总操作比例:更新操作:查找操作 = 10000:1

恰好,我也没创建Score索引。
话说,DeepSeek 的分析,正确吗?

10 回复
#2
kangss7 天前 18:26
我感觉用 select 比直接 循环更好一些

select * from A where score > 95 into cursor temp

if reccount("temp") > 0
    再scan do something
endif

“locate for”有没有索引速度相差很大,记录越多越明显

[此贴子已经被作者于2025-11-1 18:34编辑过]

#3
cssnet6 天前 09:43
myIndex 表有2000行记录,负责提供参数,用于遍历 myTable 表以生成 score值,然后测试是否出现 > 95 的结果。
其中,setNewScore() 函数很耗时,完整 Scan...Endscan 一遍外层循环,需时5个小时以上。
故而,程序对于性能异常敏感,哪怕能节省1毫秒、10毫秒,也是极好的!
我们的目标是:能抠就抠,抠到极致!
#4
kangss6 天前 11:40
不知道统计的啥,5个小时,太吓人了
大概率有很大提速空间

前几天发现记录多时, 2 个表 update,速度很慢,改用 set relation to 后 replace 速度秒完成

#5
cssnet6 天前 12:48
以下是引用kangss在2025-11-2 11:40:52的发言:

不知道统计的啥,5个小时,太吓人了
大概率有很大提速空间

前几天发现记录多时, 2 个表 update,速度很慢,改用 set relation to 后 replace 速度秒完成


尝试以不同的参数,去调用某个非常耗时的除重过程……其实这原本是 Python 的活儿,只不过既然用到了几个本地表,感觉还是 VFP 方便,就直接用 VFP 干了。
确实,VFP本地表,有无恰当的索引,执行性能相差十万八千里!
#6
吹水佬5 天前 09:54
10000记录不多,需时5个小时以上就有点夸张了。
可能是循环嵌套层次和遍历扫描次数多的问题,那是指数级的增大。
1、首先要优化代码和数据结构,尽量减少循环嵌套层次。
2、使用CDX索引,平时由系统自动维护,检索不用遍历扫描。

#7
吹水佬5 天前 10:26
以下是引用cssnet在2025-11-1 13:18:46的发言:

话说,DeepSeek 的分析,正确吗?

个人很喜欢与 DeepSeek 讨论问题,讨论得越深入问题就越清晰。
但目前看到 DeepSeek 对vfp学习得不多,vfp简单的问题基本上能给出正确的回复。很多深入点的问题回答看似是从C\C++翻译过来的,如有关指针和结构类型数据问题,她虽然知道vfp的sys(2600)与指针有关,但她给出可用sys(2600)通过返回值得到字符串的指针。但深入讨论后她会变得灵活多变,觉得很有趣。

#8
hsfisher5 天前 10:53
学习了
#9
yiyanxiyin5 天前 15:50
频繁更新又需要作为查询条件进行频繁查询的字段需要建立索引, 更新时考虑使用事务进行批量更新, 一批只会重建一次索引,从而降低多次重建索引带来的性能问题

[此贴子已经被作者于2025-11-3 15:51编辑过]

#10
cssnet4 天前 10:38
以下是引用yiyanxiyin在2025-11-3 15:50:03的发言:

频繁更新又需要作为查询条件进行频繁查询的字段需要建立索引, 更新时考虑使用事务进行批量更新, 一批只会重建一次索引,从而降低多次重建索引带来的性能问题


确实,我疏忽了!感谢指教!
其实,顶楼的代码可能应为 score 字段创建索引的。
我老眼昏花,以为要重建索引10000次,事实上,只有1次!
update mytable set score = setNewScore(lnPara)
这一句代码,其实也就相当于批量事务,VFP在内部自动维护索引时,只需重建1次。
#11
cssnet昨天 10:29
上次5个多小时顺利完成,欣欣然颇为自得,昨晚数据量大了几倍,运行到12点还没完,索性开了个通宵,任它折腾。
结果……
今早兴冲冲起身,扑向电脑,一看——哇靠!也不知是不是自动更新没关搞的鬼,电脑自动重启过一次!再一打开数据库一看,丢丢丢!通宵跑的数据全丢了!
这事件告诉我们:
任何超过5小时的程序,千万不要忘记在代码末尾加一行:
close all
或,每隔一小时左右,加一行:
flush
1