使用临时表替换WHERE IN子句

时间:2011-05-12 16:37:15

标签: sql postgresql transactions temp-tables

我让用户在表格中输入我需要查询的值列表。该列表可能非常大,并且在编译时不知道长度。而不是使用WHERE ... IN (...)我认为使用临时表并对其执行连接会更有效。我在另一个SO问题中读到了这个建议(目前找不到它,但是当我这样做时会编辑)。

要点如下:

CREATE TEMP TABLE my_temp_table (name varchar(160) NOT NULL PRIMARY KEY);

INSERT INTO my_temp_table VALUES ('hello');
INSERT INTO my_temp_table VALUES ('world');
//... etc

SELECT f.* FROM foo f INNER JOIN my_temp_table t ON f.name = t.name;

DROP TABLE my_temp_table;

如果我有两个同时进行,如果线程2尝试在线程1之后创建TEMP表,我是否会收到错误?

我应该随机生成TEMP表的名称吗?

或者,如果我将整个事物包装在事务中,命名冲突是否会消失?

这是Postgresql 8.2。

谢谢!

2 个答案:

答案 0 :(得分:3)

没有必要担心冲突。

pg_temp架构是特定于会话的。如果您在单独的会话中有并发语句,它将使用不同的模式(即使您将其视为具有相同的名称)。

然而,有两点说明:

  1. 每次创建临时对象时,系统目录都会创建临时模式和对象本身。如果频繁使用,这可能会导致混乱。

    因此,对于小集/频繁使用,通常最好坚持使用inwith语句(Postgres都能很好地处理这两种语句)。通过使用不可变集合返回函数来“欺骗”计划程序使用您正在寻找的任何计划,这也偶尔会有用。

  2. 如果您决定实际使用临时表,通常最好在填写完毕后对其进行索引和分析。除此之外,您只需撰写with声明。

答案 1 :(得分:2)

考虑使用WITH query insteed:http://www.postgresql.org/docs/9.0/interactive/queries-with.html

它还会创建临时表,在查询/事务完成时会被销毁,因此我认为应该没有并发冲突。