简体   繁体   English

为什么将数组作为文字而不是参数传递这么快?

[英]Why is it so much faster passing an array as a literal rather than a parameter?

I have a query like the following:我有如下查询:

SELECT
   table1.field1,
   table1.field2,
   table3.field1,
   table3.field2,
   table3.field3,
   table3.field4

FROM table1

INNER JOIN table2
ON table1.field1 = table2.field1

INNER JOIN table3
ON table2.field2 = table3.field5

WHERE table1.field1 = ANY(@pArray);

All of these comparisons are with string/text fields.所有这些比较都使用字符串/文本字段。 There are indexes on all of the foreign key fields.所有外键字段都有索引。 This is a poorly designed database that I have mostly just read-only access to.这是一个设计不佳的数据库,我大多只有只读访问权限。

What I'm wondering is why the above parameter causes this query to take 10+ seconds, whereas if I pass the array manually as an array literal (using string concatenation), then it takes about 40-50 milliseconds.我想知道为什么上述参数会导致此查询花费 10 多秒,而如果我将数组作为数组文字手动传递(使用字符串连接),则大约需要 40-50 毫秒。

My array contains 195 8-character numeric string elements.我的数组包含 195 个 8 个字符的数字字符串元素。

My only guess is that it has something to do with sanitizing the parameter values, but making the query take hundreds of times longer seems a bit excessive.我唯一的猜测是它与清理参数值有关,但是使查询花费数百倍的时间似乎有点过分。 What I've done is add my own check to make sure that all of the strings are 100% numeric, which I think should avoid SQL injection attacks.我所做的是添加自己的检查以确保所有字符串都是 100% 数字,我认为这应该避免 SQL 注入攻击。

My NpgSql code looks like this:我的 NpgSql 代码如下所示:

void MyQuery(
   string[] pArray
) {
   var sql = @"
      // as above
   ";

   using var connection = new NpgsqlConnection(mConnectionString);
   connection.Open();

   using var command = new NpgsqlCommand(sql, connection);
   command.Parameters.AddWithValue("pArray", pArray);

   // takes ~12 seconds with parameter, or ~50ms with array literal
   using var reader = command.ExecuteReader();

When removing the parameter, the WHERE clause ends up looking more like this, after concating:删除参数时, WHERE子句最终看起来更像这样,在连接之后:

WHERE table1.field1 = ANY('{12345678,12345679,12345680,12345681}');

Is the slowness due only to sanitization, or a bug in NpgSql, or something else?缓慢是由于清理,还是 NpgSql 中的错误,还是其他原因?

The problem as indicated in the comments was adding a parameter without specifying the type.评论中指出的问题是添加参数而不指定类型。 Changing the parameter line to the following solved the problem:将参数行更改为以下解决了该问题:

command.Parameters.AddWithValue("pArray", NpgsqlDbType.Array | NpgsqlDbType.Char, pArray);

Notice that to specify an array type, you OR the Array value with another value, in this case Char .请注意,要指定数组类型,您可以将Array值与另一个值(在本例中为Char )进行或运算。 The actual PostgreSQL type in the database is something like character varying(15) .数据库中实际的 PostgreSQL 类型类似于character varying(15)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM