请选择 进入手机版 | 继续访问电脑版
 找回密码
 立即注册

QQ登录

只需一步,快速开始

qtcxc 活字格认证

高级会员

66

主题

354

帖子

1064

积分

高级会员

积分
1064

活字格认证

qtcxc 活字格认证
高级会员   /  发表于:2020-10-4 10:49  /   查看:2473  /  回复:7
100金币
本帖最后由 qtcxc 于 2022-8-24 13:36 编辑

目前在写一个比较复杂的服务器端命令,测试过程中发现速度异常的慢,基本为不可用状态,刚开始以为是自己写的逻辑太复杂导致的执行慢的问题,经过几天的跟踪测试逐一排查最后找到问题的节点:

程序慢的原因通过,跟踪每一步执行的sql得出的结果是,在对其中一个大表插入数据时 ,用服务器端命令进行插入,插入完成后会查询遍历整个表,导致整个插入动作执行速度变慢(99%的时间在执行这个动作,如果循环插入多次则反复执行这个查询)导致整个程序执行非常慢,而这个动作的执行有什么意义?好像纯粹将整个表查询出来用一次.


进一步测试结果为:
1 用数据库客户端直接插入记录跟踪不会有这种问题(排除数据库结构引起)
2 在活字格设计器的数据库中手工操作插入数据跟踪不会有这个语句产生(排除所有活字格插入操作都会有问题的可能)
3 在活字格客户端命令(非服务器端命令)中插入数据跟踪,不会产生这个语句(排除客户端数据表操作也会有问题的可能)
4 在服务器端命令中执行数据表操作插入数据,会产生这个语句(确认只要用服务器端命令就会产生这个问题)


5 在服务器端命令中执行数据表操作插入其他表数据,也会产生类似这样的语句,但是有区别,语句的末尾是有where 条件的所以只限定一条记录,并不会有太大性能影响.


对比4和5 的语句可以看出明显的区别,4的查询时整个表所有数据都差查询出来,而5的查询只查1条记录,且语句生成方式好像也有点不一样,4是纯sql ,而5是一条动态查询语句,带了where条件返回结果只限定未1条记录

问题:

为什么服务器端命令执行插入后要查出数据,只查插入的数据还能理解,可能是要用于作为新纪录阐述 newrow 使用,但是为什么我有一个表插入后是查出这张表所有的数据并不是只查当前插入的数据?
在目前写的服务器端命令中有很多数据的插入动作,其它表都正常,却有一个表一直会出现此问题,要如何解决!


咨询:
产生这样的情况的原因是什么,如何解决此问题?


附件: 您需要 登录 才可以下载或查看,没有帐号?立即注册

最佳答案

查看完整内容

具体的底层逻辑我也是不是很清楚哈,因为很复杂高深。 但是大概的执行策略就是我上面说的,分情况的。如果数据库是用到了触发器,活字格为了保证数据的一致性,插入一条数据时就要更新查询表。

7 个回复

倒序浏览
最佳答案
最佳答案
Erik.Xue讲师达人认证 悬赏达人认证 活字格认证 Wyn认证
超级版主   /  发表于:2020-10-4 10:50:00
来自 6#
liyun654 发表于 2020-10-10 09:04
那官方的设计是,添加成功一条就查询一次,还是一次事务,不管多少条就只查询一次,mssql有些对及时准确性 ...

具体的底层逻辑我也是不是很清楚哈,因为很复杂高深

但是大概的执行策略就是我上面说的,分情况的。如果数据库是用到了触发器,活字格为了保证数据的一致性,插入一条数据时就要更新查询表。
回复 使用道具 举报
qtcxc活字格认证
高级会员   /  发表于:2020-10-4 11:37:23
2#
问题原因已找到,产生问题的原因是,在数据表中设计了一个触发器,当插入数据点额时候会执行触发器动作额外完成一些关联的动作,这是5.0的时候没有办法很好的解决事务问题时,解决数据一致性做的设计.

而就是因为这个事务的原因,跟现在服务器端命令插入数据产生了冲突,具体体现是,正常的服务器端命令插入数据是下图这样的过程:


而当这个表有触发器时执行的过程如下图:


目前解决办法是将触发器,停用,原触发器执行的动作,分离出来做成自动任务异步执行,不在数据插入时自动同步执行的方式做.

这样做的原因是,目前是在生产环境下,改版,需要兼容老的程序做法,逐步改版成6.0 的服务器端命令,还有些老的程序在使用中,无法直接一步到位放弃所有老的做法.

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复 使用道具 举报
qtcxc活字格认证
高级会员   /  发表于:2020-10-4 11:43:22
3#
对于上述情况,活字格的非服务器端命令应该是因为执行完后没有再取一次当前newrow的原因,不会出现,所以跟触发器没有任何冲突.

但是服务器端命令设计上执行完后都会取一次newrow导致出现跟触发器冲突的情况,建议官方研究一下是否应该优化避免此类冲突出现.

另外顺便提一下,服务器端命令使用过程中遇到的,创建日期 名称重复 服务器端命令执行时,不是用数据库真实的fgc_开头的英文名称执行的问题,看看是否也优化一下,我这里正好遇到这个问题,要改数据库结构来配合使用的话工程有点大,因为更改数据库字段名称,要改变正在运行的工程的程序,这个字段相关联的地方太多了.
回复 使用道具 举报
Erik.Xue讲师达人认证 悬赏达人认证 活字格认证 Wyn认证
超级版主   /  发表于:2020-10-9 16:04:55
4#
首先,数据库的操作无非是增删改查,您的这个问题,其实涉及的就是添加数据;
对于,添加数据,因为咱们在给数据添加完了数据以后,数据库能给的基本都是成功等等信息,但是其实我们还需要一个非常重要的信息就是新加的这个数据的ID(这个ID,我们会需要在很多的地方使用,比如对比数据是不是变化了,等等);一般来说,数据在添加完毕了以后,会有机智的方式直接给我返回给我们的(具体是啥我记不清了),这也就是你可以看到一般情况下,我们不会去查数据,原因就是有这个机智的方式;
但是,一旦有了触发器,数据库这个机智的方式就不行了,但是我们这边又确实需要
(为什么需要立刻知道呢?原因是我们也不知道现在会不会立刻有其他人要使用这个表的数据,修改删除什么的,如果我们不记住这个很多活字格的底层的逻辑就全乱了)

所以,没办法我们只能select去查找出来它了;

我和我们开发讨论了一下,现在的解决方案:
首先,我们这边不能修改,原因
不单单是因为我们要修改的话,这个逻辑太底层,还因为目前出了这种做法我们也想不到其他更好的做法了(能想到的其他的做法都有瑕疵);
如果我们不立刻记录这个ID,我们不能保证数据的正确性,比起保存成错误的数据,我觉得性能问题还是小角色

我们推荐您去掉你们的那边触发器,使用活字格的服务端命令去解决这个问题

我听说目前您那边去操作可能也比较麻烦,但是我们这边确实做不到了

目前最优的解决办法:
把逻辑放到存储过程,然后活字格服务端命令走完以后,直接调用存储过程命令,应该就行了。
回复 使用道具 举报
liyun654
注册会员   /  发表于:2020-10-10 09:04:45
5#
那官方的设计是,添加成功一条就查询一次,还是一次事务,不管多少条就只查询一次,mssql有些对及时准确性高的场景还是需要用到触发器
回复 使用道具 举报
qtcxc活字格认证
高级会员   /  发表于:2020-10-20 13:21:44
7#
本帖最后由 qtcxc 于 2021-2-23 14:57 编辑

我个人认为,应该有办法解决触发器跟服务器端命令冲突的问题的.(最笨的办法就是服务器端命令,在插入完数据后可以让选择是否要返回结果,通过不返回,不查询,来暂时绕开问题,然后让使用者自己想办法查出刚才插入的数据来继续执行后续的动作,这样做目前看需要放弃将同一个动作封装在事务里面不是完全的解决,但是在有些场景应该还是有用的)

而触发器产生的,的原因是旧版本对事务的支持不够全面,为了保证数据一致性选择用触发器来解决,如果当时有更好更方便的有选择的话其实不会这样做的.

目前是废了几天时间将原来的触发器拆分成多个存储过程,然后设置成定时任务的方式执行,旧版程序就等定时任务执行,而新版程序则在完成相关服务器端命令的同时手工执行一次存储过程.

虽然可以用了,但是对于一些需要同步产生的数据,变成了异步有时间差,不过数据一致性多少还是能有保障的,但是定时任务多少也增加了系统的开销,而且这样改并不是单纯的照搬原来的代码就可以,还必须考虑动作变成异步后,如何避免重复执行导致数据重复生成的问题,必须增加更多的代码和判断来实现,复杂度上也响应增加了,并不是很可取.

最彻底的方法就是,整个项目重头到尾都用活字格6.0 的服务器端命令,将所有动作都重写.(时间问题赶不上了,先按这个方法实现)

不过还是希望官方重视这个问题,因为会遇到这个问题的我觉得都还不是一上手就用6.0的新客户,而是一直跟着活字格走了几年的老客户,因为过往版本事务一致性问题而写了很多触发器来解决数据一致性问题的这部分客户.
回复 使用道具 举报
Eric.Liang讲师达人认证 悬赏达人认证 活字格认证
超级版主   /  发表于:2020-10-20 18:27:34
8#
qtcxc 发表于 2020-10-20 13:21
我个人认为,应该有办法解决触发器跟服务器端命令冲突的问题的.(最笨的办法就是服务器端命令,在插入完数据后 ...

感谢反馈,针对你描述的我们会做进一步沟通,但是不能保证是否可以去实现
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 立即注册
返回顶部