为什么将数组作为文字而不是参数传递要快得多?
Why is it so much faster passing an array as a literal rather than a parameter?
我有如下查询:
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);
所有这些比较都是针对 string/text 个字段。所有外键字段都有索引。这是一个设计不佳的数据库,我大部分时间都只有只读访问权限。
我想知道为什么上述参数导致此查询花费 10 多秒,而如果我将数组作为数组文字手动传递(使用字符串连接),则大约需要 40-50 毫秒。
我的数组包含 195 个 8 字符数字字符串元素。
我唯一的猜测是它与清理参数值有关,但让查询花费数百倍的时间似乎有点过分。我所做的是添加我自己的检查以确保所有字符串都是 100% 数字,我认为这应该避免 SQL 注入攻击。
我的 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();
删除参数时,WHERE
子句在连接后看起来更像这样:
WHERE table1.field1 = ANY('{12345678,12345679,12345680,12345681}');
缓慢仅仅是由于清理、NpgSql 中的错误或其他原因造成的吗?
评论中指出的问题是在添加参数时未指定类型。将参数行更改为以下内容解决了问题:
command.Parameters.AddWithValue("pArray", NpgsqlDbType.Array | NpgsqlDbType.Char, pArray);
请注意,要指定数组类型,您可以将 Array
值与另一个值(在本例中为 Char
)进行或运算。数据库中的实际 PostgreSQL 类型类似于 character varying(15)
.
我有如下查询:
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);
所有这些比较都是针对 string/text 个字段。所有外键字段都有索引。这是一个设计不佳的数据库,我大部分时间都只有只读访问权限。
我想知道为什么上述参数导致此查询花费 10 多秒,而如果我将数组作为数组文字手动传递(使用字符串连接),则大约需要 40-50 毫秒。
我的数组包含 195 个 8 字符数字字符串元素。
我唯一的猜测是它与清理参数值有关,但让查询花费数百倍的时间似乎有点过分。我所做的是添加我自己的检查以确保所有字符串都是 100% 数字,我认为这应该避免 SQL 注入攻击。
我的 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();
删除参数时,WHERE
子句在连接后看起来更像这样:
WHERE table1.field1 = ANY('{12345678,12345679,12345680,12345681}');
缓慢仅仅是由于清理、NpgSql 中的错误或其他原因造成的吗?
评论中指出的问题是在添加参数时未指定类型。将参数行更改为以下内容解决了问题:
command.Parameters.AddWithValue("pArray", NpgsqlDbType.Array | NpgsqlDbType.Char, pArray);
请注意,要指定数组类型,您可以将 Array
值与另一个值(在本例中为 Char
)进行或运算。数据库中的实际 PostgreSQL 类型类似于 character varying(15)
.