我让用户输入了我需要在表中查询的值列表。该列表可能非常大,并且在编译时不知道长度。与其使用 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。
谢谢!
无需担心冲突。
pg_temp架构是特定于会话的。如果您在单独的会话中有一个并发语句,它将使用不同的架构(即使您看到它具有相同的名称)。
但是,有两点需要注意:
-
每次创建临时对象时,系统目录都会创建一个临时模式和对象本身。如果经常使用,这可能会导致混乱。
因此,对于小集合/频繁使用,通常最好坚持使用
in
或with
语句(Postgres 都能很好地处理这两种语句)。通过使用不可变的集合返回函数来"诱骗"计划者使用您正在寻找的任何计划有时也很有用。 -
如果您决定实际使用临时表,通常最好在填满它们后对其进行索引和分析。否则,你所做的只是写一个
with
语句。
考虑使用 WITH 查询 insteed: http://www.postgresql.org/docs/9.0/interactive/queries-with.html
它还创建临时表,当查询/事务完成时会销毁该表,因此我认为应该没有并发冲突。