You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Using varchar(max) as a fall back parameter type causes SQL Server to make poor execution plan choices, dramatically slowing down queries.
If the type selection in sp_executesql_sql_type was better when the :sqlserver_type was missing, the system would perform MUCH better in these odd situations. Instead the quick logic falls to nvarchar(max) pretty easily:
def sp_executesql_sql_type(attr)
return attr.type.sqlserver_type if attr.type.respond_to?(:sqlserver_type)
case value = attr.value_for_database
when Numeric
value > 2_147_483_647 ? 'bigint'.freeze : 'int'.freeze
else
"nvarchar(max)".freeze
end
end
We are querying against an ERP database we have little control over and have a "through:" relationship:
the sqlserver_type is in place and the query is fine:
EXEC sp_executesql N'SELECT [OPERATION].* FROM [OPERATION] WHERE [OPERATION].[WORKORDER_TYPE] = @0 AND [OPERATION].[WORKORDER_BASE_ID] = @1 AND [OPERATION].[WORKORDER_LOT_ID] = @2 AND [OPERATION].[WORKORDER_SPLIT_ID] = @3'
, N'@0 nchar(1), @1 nvarchar(30), @2 nvarchar(3), @3 nvarchar(3)', @0 = N'W', @1 = N'2021023169', @2 = N'1', @3 = N'0'
But when loading Requirements using the :through relationship
workorder.requirements.load
the sqlserver_type is missing and then query uses nvarchar(max):
EXEC sp_executesql N'SELECT [REQUIREMENT].* FROM [REQUIREMENT] INNER JOIN [OPERATION] ON [REQUIREMENT].[WORKORDER_TYPE] = [OPERATION].[WORKORDER_TYPE] AND [REQUIREMENT].[WORKORDER_BASE_ID] = [OPERATION].[WORKORDER_BASE_ID] AND [REQUIREMENT].[WORKORDER_LOT_ID] = [OPERATION].[WORKORDER_LOT_ID] AND [REQUIREMENT].[WORKORDER_SPLIT_ID] = [OPERATION].[WORKORDER_SPLIT_ID] AND [REQUIREMENT].[WORKORDER_SUB_ID] = [OPERATION].[WORKORDER_SUB_ID] AND [REQUIREMENT].[OPERATION_SEQ_NO] = [OPERATION].[SEQUENCE_NO] WHERE [OPERATION].[WORKORDER_TYPE] = @0 AND [OPERATION].[WORKORDER_BASE_ID] = @1 AND [OPERATION].[WORKORDER_LOT_ID] = @2 AND [OPERATION].[WORKORDER_SPLIT_ID] = @3 AND [REQUIREMENT].[SUBORD_WO_SUB_ID] IS NULL'
, N'@0 nvarchar(max), @1 nvarchar(max), @2 nvarchar(max), @3 nvarchar(max)', @0 = N'W', @1 = N'2021023169', @2 = N'1', @3 = N'0'
at least in our case, sql server then picks a terrible execution plan, ignoring the obvious indexes. Changing the parameters in the query from nvarchar(max) to nvarchar(40) takes the time down from 7+seconds to 50 ms.
We have patched in "nvarchar(#{value.to_s.length + 1})".freeze
to replace the "nvarchar(max)".freeze
in sp_executesql_sql_type and it has made active record / sql server usable for our application.
The only other types this procedure will return are int and bigint if the value is numeric. This also seems a bit naïve if a float or real got into this area of code, but does not come up in our app.
The text was updated successfully, but these errors were encountered:
Using varchar(max) as a fall back parameter type causes SQL Server to make poor execution plan choices, dramatically slowing down queries.
If the type selection in sp_executesql_sql_type was better when the :sqlserver_type was missing, the system would perform MUCH better in these odd situations. Instead the quick logic falls to nvarchar(max) pretty easily:
We are querying against an ERP database we have little control over and have a "through:" relationship:
When loading Operations:
the sqlserver_type is in place and the query is fine:
But when loading Requirements using the :through relationship
the sqlserver_type is missing and then query uses nvarchar(max):
at least in our case, sql server then picks a terrible execution plan, ignoring the obvious indexes. Changing the parameters in the query from nvarchar(max) to nvarchar(40) takes the time down from 7+seconds to 50 ms.
We have patched in
"nvarchar(#{value.to_s.length + 1})".freeze
to replace the
"nvarchar(max)".freeze
in sp_executesql_sql_type and it has made active record / sql server usable for our application.
The only other types this procedure will return are int and bigint if the value is numeric. This also seems a bit naïve if a float or real got into this area of code, but does not come up in our app.
The text was updated successfully, but these errors were encountered: