AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 238518
Accepted
Joe Obbish
Joe Obbish
Asked: 2019-05-20 14:16:13 +0800 CST2019-05-20 14:16:13 +0800 CST 2019-05-20 14:16:13 +0800 CST

对于 CLR 函数输入参数使用字符串而不是 SqlString 是否安全?

  • 772

我有一个通过 C# 代码实现的 CLR 标量 UDF。我注意到,与String数据类型相比,将数据类型用于输入参数可显着提高性能SqlString。在Stairway to SQLCLR Level 5: Development (Using .NET within SQL Server)中,Solomon Rutzky提到以下原因更喜欢字符串的 SQL 数据类型:

本机公共语言运行时 (CLR) 数据类型和 SQL Server 数据类型之间的主要区别是前者不允许 NULL 值,而后者提供完整的 NULL 语义。

...

可以通过 N[VAR]CHAR 的 SqlChars、[VAR]BINARY 的 SqlBytes 和 XML 的 SqlXml.CreateReader() 来实现流值...

...

使用 SqlString(不是字符串,甚至不是 SqlChars)时,您可以访问 CompareInfo、CultureInfo、LCID 和 SqlCompareOptions 属性...

我知道我的输入永远不会为 NULL,我不需要流式传输值,我也永远不会检查排序规则属性。我的情况可能是一个例外,最好使用String而不是SqlString?如果我真的采用这种方法,有什么我应该特别注意的吗?

如果重要的话,我使用的是 SQL Server 的默认排序规则。这是我的源代码的一部分,s1作为输入参数:

fixed (char* chptr = s1)
{
    char* cp = (char*)current;

    for (int i = 0; i < s1.Length; i++)
    {
        cp[i] = chptr[i];
    }
}
sql-server sql-server-2017
  • 1 1 个回答
  • 577 Views

1 个回答

  • Voted
  1. Best Answer
    Solomon Rutzky
    2019-05-20T23:58:42+08:002019-05-20T23:58:42+08:00

    很好的问题。据我所知,在这些条件下(即保证没有NULLs 并且不需要额外的功能)不应该有任何具体的问题。这可能是类似于CURSORs 的情况,如果需要通用规则,它将是:“不要使用游标”。但是,实际规则是:“仅在适当的时候/适当的地方使用游标”。问题是教育人们了解游标的技术细节,这样他们就可以做出决定,而我们这些对这些事情有足够了解的人会忽略通用规则并继续适当地使用它们。

    因此,我建议人们“始终”使用Sql*类型,因为它可以减少混淆和错误。但是,这并不是说string在您的情况下使用不会更好。我说去做吧,如果您遇到问题string,很容易返回并将其更改为SqlString。

    关于整理和您的陈述:

    如果重要的话,我使用的是 SQL Server 的默认排序规则。

    虽然这通常无关紧要,但鉴于没有真正的默认排序规则,您在这里的意思也有点不清楚。在语言设置为“美国英语”(即 LCID = 1033)的操作系统上安装 SQL Server 时,您可能指的是不幸的默认排序规则,即SQL_Latin1_General_CP1_CI_AS. 但是仍然存在可以完全不同的三个级别的排序规则(实例/服务器、数据库和列),您可能只指这些级别中的一个甚至两个。

    我提到所有这些的原因是这里发生了一些不明显的事情:

    1. 在某种程度上,归类影响的这 3 个级别都不相关,因为 SQLCLR 线程的默认文化是操作系统级别的语言设置(所选语言的 LCID)。这会影响使用String.Equals两个StringComparison.CurrentCulture*值中的任何一个时使用的操作,以及String.Compare不指定区域性时使用的操作。

    2. 在某种程度上,归类影响的这 3 个级别都不相关,因为=运算符进行序号比较(即应该与使用_BIN2归类相同)。这也是如何String.CompareOrdinal工作的,以及String.Equals当不传递StringComparison.CurrentCulture*或StringComparison.InvariantCulture*值时。

    3. SQL Server 排序规则很重要的一个实例是将SqlString输入参数与stringvia 连接时+。在这种情况下,+运算符创建一个新SqlString的来包含的值,string以便它可以连接两个SqlStrings。问题是 newSqlString是用当前线程的 LCID(操作系统的 LCID)创建的,然后+运算符在连接之前比较两个SqlStringss(即验证它们是“相同类型”)。但是,由于SqlString输入参数具有数据库的 LCID (不是实例或列)和隐式创建的SqlString具有操作系统的 LCID,操作会出现异常,指出“排序规则”不匹配。很好,是吗?

      然而,这应该不是问题,因为没有人应该SqlString在需要字符串时直接使用该值。每个人都应该始终使用该Value属性来获取字符串。


    话虽这么说,我很好奇你做了什么测试来确定它string更快。我测试了一个简单的 UDF,它接受一个NVARCHAR(4000)输入参数,连接一个短字符串,然后返回新值。该 UDF 的一个版本接受并返回string,另一个版本接受并返回SqlString。在超过 100 万次迭代中,当比较它们的最快时间(在所有 100 万次迭代中,而不是每次)时,版本string比版本快 200-300 毫秒,大约 50% 的时间。SqlString另外 50% 的时间性能提升大约为 100 毫秒,但也可能没有。

    另外,关于您的测试代码:s1始终是直接输入参数,无论是string还是SqlString?如果是,那么您还应该测试在本地创建一个字符串并进行设置s1.Value。意义:

    string s2 = s1.Value; // when s1 is SqlString instead of string
    
    fixed (char* chptr = s2)
    {
        char* cp = (char*)current;
    
        for (int i = 0; i < s2.Length; i++)
        {
            cp[i] = chptr[i];
        }
    }
    

    此外,还有一些其他可能要测试的选项:

    1. SqlString.GetUnicodeBytes方法(返回byte[])
    2. SqlChars.Value属性(返回char[])
    • 8

相关问题

  • SQL Server - 使用聚集索引时如何存储数据页

  • 我需要为每种类型的查询使用单独的索引,还是一个多列索引可以工作?

  • 什么时候应该使用唯一约束而不是唯一索引?

  • 死锁的主要原因是什么,可以预防吗?

  • 如何确定是否需要或需要索引

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目

    • 12 个回答
  • Marko Smith

    如何让sqlplus的输出出现在一行中?

    • 3 个回答
  • Marko Smith

    选择具有最大日期或最晚日期的日期

    • 3 个回答
  • Marko Smith

    如何列出 PostgreSQL 中的所有模式?

    • 4 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    如何在不修改我自己的 tnsnames.ora 的情况下使用 sqlplus 连接到位于另一台主机上的 Oracle 数据库

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Martin Hope
    Jin 连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane 如何列出 PostgreSQL 中的所有模式? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh 为什么事务日志不断增长或空间不足? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland 列出指定表的所有列 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney MySQL 能否合理地对数十亿行执行查询? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx 如何监控大型 .sql 文件的导入进度? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve