php拼接where in,php – 为PostgreSQL中的WHERE IN子句绑定多个行和列

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

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

然后绑定一个可变长度的行集,如((‘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'))");

我需要拆分这两个的原因是因为我想要准备一次,然后以尽可能少的开销运行它多次.

解决方法:

只使用两个记录进行顺序扫描的事实毫无意义.对于如此微小的集合,索引永远不会比seqential扫描快.我构建了一个类似于你的小样本表,并用一百万行填充它,以下查询样式始终如一地生成好的计划和快速执行:

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

看来你真正的问题是如何将动态确定数量的值对绑定到你的sql.我的PHP非常生疏,阅读在线文档提醒我有多讨厌它,但我认为以下内容会做你想要的,构建上面形式的sql,并根据值的数量动态创建值对占位符的数量你希望绑定.我没有方便的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

注意::我无法找到获取行对的索引访问权限.但是如果你在两个字段的串联上创建一个功能索引,然后提供这种连接的绑定数组,你会得到一个很好的快速嵌套循环索引扫描.

标签:php,sql,postgresql

来源: https://codeday.me/bug/20190709/1416088.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值