我有一个 SQLCLR 程序集,它使用 SQL Azure 托管实例上的 LitJson 包进行简单的 JSON 反序列化。此 CLR 从一个表值函数调用,该函数仅将 JSON 属性作为表返回(理论上比 T-SQL 中的内置 JSON 处理更快)。
奇怪的是,程序集在卸载时(即它没有出现在 中sys.dm_clr_loaded_assemblies
)比加载时运行得快得多。对于某些颜色,卸载时我可以在约 200 毫秒内反序列化 1,000 条记录,而加载程序集时,相同的 1,000 条记录需要约 7 秒。
我有一个解决方法,即在我的查询开始时,我PERMISSION_SET
来回UNSAFE
切换EXTERNAL_ACCESS
强制卸载程序集,但这感觉就像一个黑客。程序集的加载速度应该比卸载速度快。
这里的任何想法将不胜感激。代码如下所示——根本没有什么花哨的地方。
[SqlFunction(FillRowMethodName = "FillRowMessageParser", IsDeterministic = true)]
public static IEnumerable ParseRows(string MsgText)
{
DatabaseRow[] myRows;
//LitJson doing its work here
myRows= JsonMapper.ToObject<DatabaseRow[]>(MsgText);
return myRows;
}
public static FillRowMessageParser(object obj, out SqlChars Field1, out SqlChars Field2, [bunch more out fields here])
{
var myRow = (DatabaseRow)obj;
//Set a bunch of fields to the out variables here
Field1 = new SqlChars(myRow.Property1);
//whole bunch more here
//loop through some nested properties of the myRow class
foreach (var x in myRow.Object1)
{
switch(x.Name)
{
case "1": Field2 = new SqlChars(x.Value); break;
//whole bunch more here
}
}
}
SQL 组件如下所示:
DECLARE @JSON NVARCHAR(MAX) =
(
SELECT
TOP 1000
MessageID,
JSON_QUERY(MessageText) AS MessageText
FROM MyTable
ORDER BY 1 ASC
FOR JSON AUTO
)
DECLARE @Start DATETIME2
DECLARE @End DATETIME2
SET @Start = SYSDATETIME()
SELECT *
FROM MyCLRTableValuedFunction(@JSON)
SET @End = SYSDATETIME()
SELECT DATEDIFF(MILLISECOND,@Start, @End) --Time CLR takes to process
更新
看来问题与 LitJson 包本身有关。我们最终尝试将 JsonFx 作为另一个不需要任何不受支持的 SQL Server .NET 库的包(向@SolomonRudzky 提出建议),但无论出于何种原因,该包在反序列化中的性能,这就是我们的练习,是不如原生 T-SQL JSON 处理(至少对于我们的数据集)。所以我们最终放弃了 SQLCLR 并返回到 T-SQL 来完成这个过程。T-SQL 中的性能仍然不如卸载的 LitJson 包,但它足以满足我们的需求,并且避免了在每次调用 CLR 时卸载程序集的太多不稳定的解决方法。