对索引的 SQL 输入参数过滤默认为 nvarchar 导致全表扫描

Posted

技术标签:

【中文标题】对索引的 SQL 输入参数过滤默认为 nvarchar 导致全表扫描【英文标题】:SQL input parameters filtering on indexes are defaulting to nvarchar causing full table scans 【发布时间】:2020-11-10 20:21:52 【问题描述】:

当我们的应用程序通过 ADO.Net 提交带有输入参数的 SQL 时,参数定义默认为 nvarchar。如果该字段在数据库表上定义为 varchar 和索引,则不使用索引,从而导致扫描而不是查找。我们正在从 Teradata 转换到 SQL Server,因此这是转换过程中的系统性问题。申请团队将此提交给我:

当我们在代码中将任何内容定义为字符串时,ADO.Net 提供程序会自动假定这是一个 SQLServer 中的 NVarchar。

他们的解决方案之一是仅针对超过 1,000 行的表解决此问题。我认为这在很多层面上都有问题,但我正在寻找一些额外的输入。

我是一名 Teradata DBA,正在过渡到 MSSQL DBA。

我假设 ADO.Net 中的这个设置是可配置的。对我来说,很明显 Input 参数定义需要与表中的字段定义相匹配,尤其是当它是索引的一部分时会导致全表扫描。

谁能帮我解决(1)如何设置输入参数定义以匹配表定义?(2)如果这是系统性的,为什么只修复这些参数和查询会是一个坏主意,如果表的大小超过 1,000 条记录?

【问题讨论】:

我的猜测是开发人员正在创建参数AddWithValue,它根据值的 .NET 类型猜测 SQL Server 类型。 .NET 中的字符串是 Unicode,所以它猜测 varchar 是错误的。解决方案是显式指定正确的参数类型以匹配 db 架构。 嗨@Joe - 客户端编程问题是off-topic 用于Database Administrators。如果您正在寻求一种对 .Net 客户端代码进行编程的方法,应该在 Stack Overflow 上询问。但是,如果您询问在数据库中 错误键入代码对性能的影响,那么这将是主题,但需要在您的问题中进行澄清。即,如果您询问为什么参数应该是强类型的,由于服务器端的性能影响,这可能被认为是主题。 【参考方案1】:

正如您在下面的代码中看到的,您可以在该表单中指定参数的数据类型

    connection.Open();
    SqlCommand command = new SqlCommand(null, connection);

    // Create and prepare an SQL statement.
    command.CommandText =
        "INSERT INTO Region (RegionID, RegionDescription) " +
        "VALUES (@id, @desc)";
    SqlParameter idParam = new SqlParameter("@id", SqlDbType.Int, 0);
    SqlParameter descParam =
        new SqlParameter("@desc", SqlDbType.Text, 100);
    idParam.Value = 20;
    descParam.Value = "First Region";
    command.Parameters.Add(idParam);
    command.Parameters.Add(descParam);

见Microsoft descriction of prepared statements

【讨论】:

以上是关于对索引的 SQL 输入参数过滤默认为 nvarchar 导致全表扫描的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server - 按可变数量的参数过滤查询

MongoDB通过许多参数过滤(复合索引与否)

关于CI xss进攻和sql注入的防范问题

sql server 2005 一个索引多个字段,字段的排列顺序对搜索有啥影响??

13sql注入修复

SQL case 语句不适用于多参数 pentaho cde