gpt4 book ai didi

php - 为 PostgreSQL 中的 WHERE IN 子句绑定(bind)多行和多列

转载 作者:可可西里 更新时间:2023-10-31 23:42:54 25 4
gpt4 key购买 nike

所以我想准备一个类似这样的查询:

SELECT id FROM users WHERE (branch, cid) IN $1;

然后绑定(bind)一组可变长度的行,如 (('a','b'),('c','d')) 到它。

换句话说,像这样:

pg_prepare($users, 'users_query', 'SELECT id FROM users WHERE (branch, cid) IN $1');
$result = pg_execute($users, 'users_query', array("(('a','b'),('c','d'))");

我需要将两者分开的原因是因为我想准备一次,然后以尽可能少的开销运行多次。

最佳答案

仅对两条记录进行顺序扫描这一事实毫无意义。对于如此小的集合,索引永远不会比顺序扫描更快。我构建了一个类似于您的示例表,并用一百万行填充它,并且以下查询样式始终如一地产生良好的计划和快速的执行:

prepare s4 as
select id from users
join (select * from (values ($1,$2),($3,$4)) as v(branch, cid)) as p
using (branch, cid);

explain analyze execute s4('b11','c11','b1234','c1234');
QUERY PLAN
------------------------------------------------------------------------------------------------------------------
Nested Loop (cost=0.00..16.65 rows=1 width=4) (actual time=0.199..0.234 rows=2 loops=1)
-> Values Scan on "*VALUES*" (cost=0.00..0.03 rows=2 width=64) (actual time=0.002..0.003 rows=2 loops=1)
-> Index Scan using u_i on users (cost=0.00..8.30 rows=1 width=16) (actual time=0.111..0.112 rows=1 loops=2)
Index Cond: ((users.branch = "*VALUES*".column1) AND (users.cid = "*VALUES*".column2))
Total runtime: 0.425 ms

看来您真正的问题是如何将动态确定数量的值对绑定(bind)到您的 sql。我的 PHP 非常生锈,阅读在线文档让我想起了我是多么厌恶它,但我认为下面会做你想做的,用基于值的数量动态创建的值对占位符的数量构建上面形式的 sql你想绑定(bind)。我手边没有 php 执行环境,所以我什至没有检查它在语法上是否正确,但您应该能够理解并解决我示例中的任何小错误。

$values = array(
'a', 'b',
'c', 'd',
// etc...
);

$value_placeholders = "";
$sep = "";
for ($i=1; $i <= $count($values); $i+=2) {
$value_placeholders = $value_placeholders . sprintf("($%u,$%u),", $i, $i+1) . $sep
$sep = ",";
}

$sql =
'select id from users ' .
'join (select * from (values ' . $value_placeholders . ') as v(branch, cid)) as p' .
'using (branch, cid)';

$result = pg_query_params($dbconn, $sql, $values);

如果您真的只需要一个准备好的语句(并且对于一个懒得实际尝试针对真实数据集而不是两条记录进行查询的人,我们将完全避免谈论 premature optimization ), 我想我有一个答案:

create index u_i2 on users ((branch||cid));
prepare sa as select id from users where branch||cid in (select unnest($1::text[]));
explain analyze execute sa(ARRAY['b1c1','b1234c1234']);
QUERY PLAN
----------------------------------------------------------------------------------------------------------------------
Nested Loop (cost=12.17..645.78 rows=50000 width=4) (actual time=0.169..0.188 rows=2 loops=1)
-> HashAggregate (cost=0.02..0.03 rows=1 width=32) (actual time=0.018..0.019 rows=2 loops=1)
-> Result (cost=0.00..0.01 rows=1 width=0) (actual time=0.010..0.011 rows=2 loops=1)
-> Bitmap Heap Scan on users (cost=12.14..638.25 rows=500 width=16) (actual time=0.082..0.082 rows=1 loops=2)
Recheck Cond: ((users.branch || users.cid) = (unnest($1)))
-> Bitmap Index Scan on u_i2 (cost=0.00..12.02 rows=500 width=0) (actual time=0.078..0.078 rows=1 loops=2)
Index Cond: ((users.branch || users.cid) = (unnest($1)))
Total runtime: 0.275 ms

注意:我无法找到对行对进行索引访问的途径。但是,如果您对两个字段的串联创建一个函数索引,然后提供此类串联的绑定(bind)数组,您将获得一个不错的快速 nest-loop-index-scan。

关于php - 为 PostgreSQL 中的 WHERE IN 子句绑定(bind)多行和多列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9791475/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com