以文本方式查看主题 - Foxtable(狐表) (http://foxtable.net/bbs/index.asp) -- 专家坐堂 (http://foxtable.net/bbs/list.asp?boardid=2) ---- 请教【提取表A not in 表B的行】的性能问题,表B-SQLGetComboListString后再用表A-SQLSelect (Not in) 的方法是正解吗? (http://foxtable.net/bbs/dispbbs.asp?boardid=2&id=95483) |
-- 作者:chen3728060 -- 发布时间:2017/1/21 9:15:00 -- 请教【提取表A not in 表B的行】的性能问题,表B-SQLGetComboListString后再用表A-SQLSelect (Not in) 的方法是正解吗? 问题1:我有表A和表B 2个商品档案表。我现在需要找出表A不在表B的行。我用的方法是
Dim s As String = DataTables("表B").SQLGetComboListString("ItemID")
但是我在想,如果我将来表B的行很多,那这个 s就会很长很大,好像性能会非常差。
我记得sql语言里,有个一个表join另外一个表然后not in的方法,但好像这个需要2个表全部行都做内连接,好像性能也不高哪里去。 这里使用Replace做成的数据字符串,如果我用SqlGetValues的方法后配合一个For each 做成数据字符串,这个性能高吗?
请问大家有什么【提取表A not in 表B的行】正确方法?
附:我的表B是在国外服务器数据库上,网速慢,我的表A 是本地SQL,所以我得尽可能减少提取表B的要消耗的数据传输。
---------------------------------- 问题2:假如我的表B是一个国外服务器的总部库存流水表,表A是个本地库存流水表,每天表A需要上传自己的库存流水追加到总部的表B里。
①采用表A not in 表B的行都上传,哪怕这次网路不稳定传漏了,下次再传也会补上,这样就绝对可以保证不会有漏了的行。但是性能呢?流水表是一个1个月后就会膨胀很厉害的东西。
②采用表A增加一个逻辑字段,标记是否已经上传,传了的就设置为true。传的时候,只判断这个逻辑是否为false,是false就传。 但是有问题,如果我传输时网络出问题,这个行在总部没有新建,但是本地就认为已经传了,设置为true了,这样它下次也不会回传给总部,总部的库存就不一致。(这一般很少发生,从代码执行的顺序来说,这个情况理论上不存在,毕竟是先总部新建行,保存成功,本地行才会设置为true,并保存) 又或者总部已经新建了,但是本地刚好死机,认为还没有传,下次又再传,造成流水重复,这个问题容易发生,例如一天要传1000个行,肯定要个20秒左右,毕竟国外服务器,20秒内突然断电或者有人脑残以为软件死了强制关闭了软件,这都是有可能的。(可能有的人会叫我传的时候先检测有总部有没这个流水号,那实际上已经跟①的方法一样,而且每一行的上传都SqlFind遍历了一次总部的流水表,性能更加差)
大家对流水表上传,有啥看法?
其实我不需要性能最优化最强的,只是想要一个比较适中妥当,数据架构简单可靠的。 [此贴子已经被作者于2017/1/21 9:27:34编辑过]
|
-- 作者:有点蓝 -- 发布时间:2017/1/21 9:41:00 -- 1、使用事务,如果不喜欢出错后一次性回滚全部,可以把上传的数据分批处理,比如一天要传1000个行,分成10次,每次100行,这100行在一个事务中,这样出错就只回滚100行。 2、如果上传后表B数据都是新增的可以考虑使用SqlBulkCopy:http://foxtable.com/bbs/dispbbs.asp?BoardID=2&ID=91737 3、2个表都增加一个时间列,所有新增的行都记录新增时的服务器时间,表B增加一个标记列,标记是哪个客户端上传的数据。 那么客户端在上传表A数据的时候只需要上传比之前本客户端上传的数据时间晚的数据即可,无需通过“ItemID not in”查询再上传。 4、数据同步可以做到一个独立的项目中,在服务器后台定时上传,或者手工通知后上传。这样就不会存在普通操作人员认为软件假死的现象了
|
-- 作者:chen3728060 -- 发布时间:2017/1/21 10:15:00 -- 回复:(有点蓝)1、使用事务,如果不喜欢出错后一次性... 1的话,虽然是好办法,但是要写好多代码,没办法利用到狐表的各种行操作的便利性 例如 dr.save 。我的系统,应该去不到这么严谨
2的话,要琢磨下这个工具,狐表没有给。貌似也没有这么多数据啦,一天分多次,薄利多销,内存开销也小
3这个思路很不错,这种避免not in 的库存流水表上传思路。
最后,还有一个问题没解决,就是表A和表B,找出不存在的行,这次表A和表B不是库存流水表,就是2个很独立表,例如 学生手册,某次参考宴会学生的手册。我需要找出这次没参加宴会的学生。用not in?还是用?
|
-- 作者:有点蓝 -- 发布时间:2017/1/21 10:27:00 -- 不同的数据源,也就只能这样子了。 或者考虑使用join,join比not in高效多了,完全不是一个级别的,数据越多效率差别越明显 1、使用存储过程,把表B,SQLGetComboListString获取的ID传入,在存储过程生成ID的临时表,然后使用join连接取数据 2、把表B,SQLGetComboListString获取的ID保存到表A数据库的一个缓存数据表中,同样使用join连接取数据,然后清空缓存数据表数据
|
-- 作者:有点蓝 -- 发布时间:2017/1/21 10:31:00 -- 其实使用事务也多不了多少代码,这种数据同步的操作应该可以批量处理的,无需逐行处理,除非还要逐个做数据加工。 作为一个开发者怕写多代码也不应该了。
|
-- 作者:chen3728060 -- 发布时间:2017/1/22 22:09:00 -- 回复:(有点蓝)不同的数据源,也就只能这样子了。或... 我还想到一个,就是用sqlgetValues得到一个集合,然后用集合是否contains表A的某行,不包含就上传,这样的效率如何?
|
-- 作者:chen3728060 -- 发布时间:2017/1/22 22:18:00 -- 回复:(有点蓝)不同的数据源,也就只能这样子了。或... 用sqlGetCombolist怎么放进去一个临时表里最快?我目前只想到用SQLJoinTableBuilder,配合里面的Distinct和Filter功能,直接生成一个临时表 |
-- 作者:有点色 -- 发布时间:2017/1/22 22:44:00 -- 以下是引用chen3728060在2017/1/22 22:09:00的发言:
我还想到一个,就是用sqlgetValues得到一个集合,然后用集合是否contains表A的某行,不包含就上传,这样的效率如何?
这种方法,你还是得把表a的行都加载出来才能比较,效率比较低。 |
-- 作者:有点色 -- 发布时间:2017/1/22 22:46:00 -- 以下是引用chen3728060在2017/1/22 22:18:00的发言:
用sqlGetCombolist怎么放进去一个临时表里最快?我目前只想到用SQLJoinTableBuilder,配合里面的Distinct和Filter功能,直接生成一个临时表
你要单独做一个数据表【表AAA】,然后加一列【ItemID】,然后把表B的值都填入这个表。接着【表AAA】和【表A】进行join连接得到查询表 |