【DM版本】:DM8
【操作系统】:服务端:麒麟高级服务器V10, 客户端:Win10
【CPU】: x86_64
【问题描述】*:.NET6 请求执行超时。
引用包:
<PackageReference Include="dmdbms.DmProvider" Version="1.1.0.16649" />
<PackageReference Include="dmdbms.Microsoft.EntityFrameworkCore.Dm" Version="6.0.16.16649" />
场景1: 在DM管理工具中执行sql语句,耗时:4s多,在程序中执行,报超时,超时时间设置为15s。
efcore 生成的脚本:2024-03-06 10:43:05.4366||Debug||Microsoft.EntityFrameworkCore.Database.Command||Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='15']
SELECT "p"."CODE", "p"."CLASS", "p"."CLASS_CODE", "p"."CREATE_DATE", "p"."CREATE_USER", "p"."DIY", "p"."HOSPITAL_CODE", "p"."HOSPITAL_GROUP_CODE", "p"."ICD_SECTIONS_CODE", "p"."IS_DELETED", "p"."IS_GRAY", "p"."MODIFY_DATE", "p"."MODIFY_USER", "p"."NAME", "p"."NATIONAL_CODE", "p"."PIN_YIN", "p"."REMARK", "p"."USE_YS_OR_BA", "p"."WU_BI", "p"."YB_CODE", "p"."YB_NAME"
FROM "PBT_ICD_ITEMS" AS "p"||||end
错误内容:2024-03-06 10:43:09.6570|Microsoft.EntityFrameworkCore.Query|ERROR|An exception occurred while iterating over the results of a query for context type 'XMBT.Repository.EFCore.EFCoreDbContext'.
Dm.DmException (0x80004005): 请求执行超时
at Dm.DmError.ThrowDmException(DmError err)
at Dm.DmResp.ThrowServerException(DmMsg msg, String charSet, Boolean rwStandby)
at Dm.DmResp.Fetch(DmMsg msg, Int64 rowPos, DmResultSetCache rsCache)
at Dm.DmResultSetCache.FetchNext()
at Dm.DmDataReader.do_Read()
at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable1.Enumerator.MoveNext()请求执行超时 at Dm.DmError.ThrowDmException(DmError err) at Dm.DmResp.ThrowServerException(DmMsg msg, String charSet, Boolean rwStandby) at Dm.DmResp.Fetch(DmMsg msg, Int64 rowPos, DmResultSetCache rsCache) at Dm.DmResultSetCache.FetchNext() at Dm.DmDataReader.do_Read() at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable
1.Enumerator.MoveNext()
at System.Collections.Generic.List1..ctor(IEnumerable
1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
at XMBT.HIS.PB.BLL.PB_ICDItemsBLL.<WritingCacheAsync>b__4_0() in D:\byte-info\XMBT.His\XMBT.HIS.Server\XMBT.HIS.PublicServices\XMBT.HIS.PB.BLL\PB_ICDItemsBLL.cs:line 131
at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location ---
at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread)
--- End of stack trace from previous location ---
at XMBT.Core.Cache.CacheFactory.<StartAsync>b__4_1(Type type)
at System.Threading.Tasks.Task.<>c.<ThrowAsync>b__128_1(Object state)}
场景2:同一个sql语句,DbCommand.CommandTimeout 设置值15s返回超时,设置1500s,返回成功,实际sql执行时间毫秒级。
执行sql语句如下:
2024-03-06 12:15:12.1217||Info||XMBT.Repository.EFCore.EFCoreRepository`1||执行Sql语句:
select
oi.CODE,
oi.ORDER_TYPE_CODE,
oi.CODE AS ORDER_ITEM_CODE,
oi.COMBINATION_ITEM_CODE,
oi.CHARGE_ITEM_CODE,
oi.EXAM_TYPE_CODE,
ci.CHARGE_ITEM_NAME,
ci.CHARGE_ITEM_NAME AS PRINT_NAME,
ci.AUDIT_CODE,
ci.MZ_CLASS_CODE as ITEM_CLASS_CODE,
ci.MEDICAL_CLASS_CODE,
cip.ITEM_PRICE AS UNIT_PRICE,
cip.ITEM_PRICE,
oi.EXEC_DEPT_CODE,
oi.CHARGE_FLAG,
1 AS AMOUNT,
2 AS CHARGE_FREQUENCY,
ci.ITEM_SPEC AS SPECIFICATION,
ci.EXCLUSIONS,
ci.CONNOTATION,
oi.SEX_TYPE,
ci.ITEM_UNIT AS ITEM_UNIT_CODE,
ciu.NAME AS ITEM_UNIT_NAME,
ci.LOCAL_CHARGE_CODE,
oi.EXTEND_FLAG1,
oi.IS_PACS
,oi.HOSPITAL_CODE
FROM XMBT_PBD.PBT_ORDER_ITEM oi
left join XMBT_PBD.PBT_CHARGE_ITEM ci ON ci.CODE = oi.CHARGE_ITEM_CODE and ci.IS_DELETED = 0
left join XMBT_PBD.PBT_CHARGE_ITEM_PRICE cip ON cip.CHARGE_ITEM_CODE = oi.CHARGE_ITEM_CODE and cip.IS_DELETED = 0 and cip.START_DATE<= GETDATE() and GETDATE() <ISNULL(cip.STOP_DATE,'9999-12-31')
left join XMBT_DBD.DBT_CHARGE_ITEM_UNIT ciu ON ciu.CODE = ci.ITEM_UNIT
WHERE oi.IS_DELETED = 0
and oi.COMBINATION_ITEM_CODE is null
and oi.STATUS = 0
and exists(SELECT 1 FROM TABLE(XMBT_SYS.UFN_SPLIT_STR(:Codes,','))WHERE col = oi.CODE)
union
select
oi.CODE,
oi.ORDER_TYPE_CODE,
oi.CODE AS OrderItemCode,
oi.COMBINATION_ITEM_CODE,
ci.CODE AS ChargeItemCode,
oi.EXAM_TYPE_CODE,
ci.CHARGE_ITEM_NAME,
ci.CHARGE_ITEM_NAME AS PrintName,
ci.AUDIT_CODE,
ci.MZ_CLASS_CODE as ItemClassCode,
ci.MEDICAL_CLASS_CODE,
cip.ITEM_PRICE AS UnitPrice,
cip.ITEM_PRICE,
oi.EXEC_DEPT_CODE,
oi.CHARGE_FLAG,
cd.AMOUNT,
2 AS ChargeFrequency,
ci.ITEM_SPEC AS Specification,
ci.EXCLUSIONS,
ci.CONNOTATION,
oi.SEX_TYPE,
ci.ITEM_UNIT AS ItemUnitCode,
ciu.NAME AS ItemUnitName,
ci.LOCAL_CHARGE_CODE,
oi.EXTEND_FLAG1,
oi.IS_PACS
,oi.HOSPITAL_CODE
FROM XMBT_PBD.PBT_ORDER_ITEM oi
join XMBT_PBD.PBT_COMBINATION_ITEM_DETAIL cd ON oi.COMBINATION_ITEM_CODE = cd.COMBINATION_ITEM_CODE and cd.IS_DELETED = 0
left join XMBT_PBD.PBT_CHARGE_ITEM ci ON ci.CODE = cd.CHARGE_ITEM_CODE and ci.IS_DELETED = 0
left join XMBT_PBD.PBT_CHARGE_ITEM_PRICE cip ON cip.CHARGE_ITEM_CODE = ci.CODE and cip.IS_DELETED = 0 and cip.START_DATE<= GETDATE() and GETDATE() <ISNULL(cip.STOP_DATE,'9999-12-31')
left join XMBT_DBD.DBT_CHARGE_ITEM_UNIT ciu ON ciu.CODE = ci.ITEM_UNIT
WHERE oi.IS_DELETED = 0
and oi.COMBINATION_ITEM_CODE is not null
and cd.ITEM_SOURCE = 0
and oi.STATUS = 0
and exists(SELECT 1 FROM TABLE(XMBT_SYS.UFN_SPLIT_STR(:Codes,','))WHERE col = oi.CODE)
union
select
oi.CODE,
dos.DRUG_TYPE_CODE AS OrderTypeCode,
oi.CODE AS OrderItemCode,
oi.COMBINATION_ITEM_CODE,
dos.CODE AS ChargeItemCode,
oi.EXAM_TYPE_CODE,
dos.NAME AS ChargeItemName,
dp.NAME AS PrintName,
doi.HS_TYPE AS AuditCode,
doi.MZ_TYPE AS ItemClassCode,
doi.BA_TYPE AS MedicalClassCode,
dos.SELL_PIECE_PRICE AS UnitPrice,
dos.SELL_PIECE_PRICE AS ItemPrice,
null AS ExecDeptCode,
1 AS ChargeFlag,
cd.AMOUNT,
2 AS ChargeFrequency,
dos.PACK_SPECIFICATION AS Specification,
'' Exclusions,
'' Connotation,
oi.SEX_TYPE,
doi.BASE_UNIT AS ItemUnitCode,
doi.BASE_UNIT_NAME AS ItemUnitName,
dos.ORDER_STOCK_CODE AS LocalChargeCode,
oi.EXTEND_FLAG1,
oi.IS_PACS
,oi.HOSPITAL_CODE
FROM XMBT_PBD.PBT_ORDER_ITEM oi
join XMBT_PBD.PBT_COMBINATION_ITEM_DETAIL cd ON oi.COMBINATION_ITEM_CODE = cd.COMBINATION_ITEM_CODE and cd.IS_DELETED = 0 and cd.ITEM_SOURCE = 1
join XMBT_DMS.DMS_DRUG_ORDER_STOCK dos ON cd.CHARGE_ITEM_CODE = dos.ORDER_STOCK_CODE
JOIN XMBT_DMS.DMS_DRUG_ORDER_ITEM doi ON dos.ORDER_ITEM_CODE = doi.CODE
JOIN XMBT_DMS.DMS_DRUG_PRESCRIPTION dp ON doi.PRESCRIPTION_CODE = dp.CODE and dp.IS_DELETED = 0
where dos.IS_DELETED = 0
and doi.IS_DELETED = 0
and oi.IS_DELETED = 0
and oi.STATUS = 0
and exists(SELECT 1 FROM TABLE(XMBT_SYS.UFN_SPLIT_STR(:Codes,','))WHERE col = oi.CODE)
参数:
{"Codes": "3a2580b0-7a1b-4c3a-9862-f0a364b4d3b9"}
耗时:194毫秒||||end
代码如下:
timeout = 15时,报错如下:
Dm.DmException
HResult=0x80004005
Message=请求执行超时
Source=DmProvider
StackTrace:
在 Dm.DmCommand.do_ExecuteDbDataReader(CommandBehavior behavior)
在 XMBT.Repository.EFCore.EFCoreRepository1.ExecuteSqlQueryToDataTable(String sql, Dictionary
2 parameters, Int32 timeout) 在 XMBT.Repository.EFCore\EFCoreRepository.cs 中: 第 1047 行
在 XMBT.Repository.EFCore.EFCoreRepository1.SqlQuery[TResult](String sql, Object param) 在 XMBT.Repository.EFCore\EFCoreRepository.cs 中: 第 916 行 在 XMBT.Core.BaseRepository
1.SqlQuery[TResult](String sql, Object param) 在 D:\byte-info\XMBT\src\XMBT.Server\XMBT.Infrastructures\XMBT.Core\BaseRepository.cs 中: 第 779 行
在 XMBT.HIS.PB.DAL.PB_OrderItemDAL.GetOrderItemList(PBQueryParams queryParams) 在 D:\byte-info\XMBT.His\XMBT.HIS.Server\XMBT.HIS.PublicServices\XMBT.HIS.PB.DAL\PB_OrderItemDAL.cs 中: 第 55 行
在 XMBT.HIS.PB.BLL.PB_OrderItemBLL.GetOrderItemList(PBQueryParams queryParams) 在 D:\byte-info\XMBT.His\XMBT.HIS.Server\XMBT.HIS.PublicServices\XMBT.HIS.PB.BLL\PB_OrderItemBLL.cs 中: 第 282 行
在 XMBT.HIS.MZMWS.BLL.MZ_MedicalOrderBLL.BuildRegisterOrderList(PB_VisitRecordDto dto) 在 D:\byte-info\XMBT.His\XMBT.HIS.Server\XMBT.HIS.MZServices\XMBT.HIS.MZMWS.BLL\MZ_MedicalOrderBLL.cs 中: 第 6244 行
此异常最初是在此调用堆栈中引发的:
Dm.DmCommand.do_ExecuteDbDataReader(System.Data.CommandBehavior)
XMBT.Repository.EFCore.EFCoreRepository<TEntity>.ExecuteSqlQueryToDataTable(string, System.Collections.Generic.Dictionary<string, object>, int) (位于 EFCoreRepository.cs 中)
XMBT.Repository.EFCore.EFCoreRepository<TEntity>.SqlQuery<TResult>(string, object) (位于 EFCoreRepository.cs 中)
XMBT.Core.BaseRepository<TEntity>.SqlQuery<TResult>(string, object) (位于 BaseRepository.cs 中)
XMBT.HIS.PB.DAL.PB_OrderItemDAL.GetOrderItemList(XMBT.HIS.Core.Models.Param.PBQueryParams) (位于 PB_OrderItemDAL.cs 中)
XMBT.HIS.PB.BLL.PB_OrderItemBLL.GetOrderItemList(XMBT.HIS.Core.Models.Param.PBQueryParams) (位于 PB_OrderItemBLL.cs 中)
XMBT.HIS.MZMWS.BLL.MZ_MedicalOrderBLL.BuildRegisterOrderList(XMBT.HIS.PB.Models.PB_VisitRecordDto) (位于 MZ_MedicalOrderBLL.cs 中)
表,列,索引收集下统计信息
要注意两个问题,目前不好判断,可以结合SQL日志进一步在分析下。
1)看看是不是具体参数,和绑定参数的执行计划存在差异
2)看看是不是计划缓存影响的等。
总之,【一样】的执行方式,不会有两个效率的。