Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/xamarin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PostgreSQL中非常慢的词典排序?_Postgresql_Postgresql 8.4_Postgresql Performance - Fatal编程技术网

PostgreSQL中非常慢的词典排序?

PostgreSQL中非常慢的词典排序?,postgresql,postgresql-8.4,postgresql-performance,Postgresql,Postgresql 8.4,Postgresql Performance,我有一个vote\u pairs视图,如下所示: CREATE VIEW vote_pairs AS SELECT v1.name as name1, v2.name as name2, ... FROM votes AS v1 JOIN votes AS v2 ON v1.topic_id = v2.topic_id; 而且,在投票表中有大约100k行,跨此视图执行查询大约需要3秒钟 但是,当我在名称上添

我有一个
vote\u pairs
视图,如下所示:

CREATE VIEW vote_pairs AS
    SELECT
        v1.name as name1,
        v2.name as name2,
        ...
    FROM votes AS v1
    JOIN votes AS v2
        ON v1.topic_id = v2.topic_id;
而且,在
投票表中有大约100k行,跨此视图执行查询大约需要3秒钟

但是,当我在名称上添加附加过滤器时:

… ON v1.topic_id = v2.topic_id AND v1.name < v2.name;
发生什么事了?博士后的词典比较慢吗?这是别的吗?如何提高查询速度

投票表:

CREATE TABLE votes (
    topic_id INTEGER REFERENCES topics(id),
    name VARCHAR(64),
    vote VARCHAR(12)
)

CREATE INDEX votes_topic_name ON votes (topic_id, name);
CREATE INDEX votes_name ON votes (name);
EXPLAIN ANALYZE
的输出不带名称过滤器:

db=# CREATE OR REPLACE VIEW vote_pairs AS
db-#     SELECT
db-#         v1.name as name1,
db-#         v2.name as name2
db-#     FROM votes AS v1
db-#     JOIN votes AS v2
db-#         ON v1.topic_id = v2.topic_id;
CREATE VIEW
db=# EXPLAIN ANALYZE SELECT * FROM vote_pairs;                                                                                                                                                                                                                           QUERY PLAN                                                          
-----------------------------------------------------------------------------------------------------------------------------
 Hash Join  (cost=3956.38..71868.56 rows=5147800 width=28) (actual time=51.810..1236.673 rows=5082750 loops=1)
   Hash Cond: (v1.topic_id = v2.topic_id)
   ->  Seq Scan on votes v1  (cost=0.00..1882.50 rows=112950 width=18) (actual time=0.019..18.358 rows=112950 loops=1)
   ->  Hash  (cost=1882.50..1882.50 rows=112950 width=18) (actual time=50.671..50.671 rows=112950 loops=1)
         ->  Seq Scan on votes v2  (cost=0.00..1882.50 rows=112950 width=18) (actual time=0.004..20.306 rows=112950 loops=1)
 Total runtime: 1495.963 ms
(6 rows)
使用过滤器:

db=# CREATE OR REPLACE VIEW vote_pairs AS
db-#     SELECT
db-#         v1.name as name1,
db-#         v2.name as name2
db-#     FROM votes AS v1
db-#     JOIN votes AS v2
db-#         ON v1.topic_id = v2.topic_id AND v1.name < v2.name;
CREATE VIEW
db=# EXPLAIN ANALYZE SELECT * FROM vote_pairs;
                                                         QUERY PLAN                                                          
-----------------------------------------------------------------------------------------------------------------------------
 Hash Join  (cost=3956.38..84738.06 rows=1715933 width=28) (actual time=66.688..6900.478 rows=2484900 loops=1)
   Hash Cond: (v1.topic_id = v2.topic_id)
   Join Filter: ((v1.name)::text < (v2.name)::text)
   ->  Seq Scan on votes v1  (cost=0.00..1882.50 rows=112950 width=18) (actual time=0.023..24.539 rows=112950 loops=1)
   ->  Hash  (cost=1882.50..1882.50 rows=112950 width=18) (actual time=65.603..65.603 rows=112950 loops=1)
         ->  Seq Scan on votes v2  (cost=0.00..1882.50 rows=112950 width=18) (actual time=0.004..26.756 rows=112950 loops=1)
 Total runtime: 7048.740 ms
(7 rows)
杂项说明:

  • 真空满
    分析投票
    已运行
  • 8.4.11和9.2.3的行为方式相同

我猜之所以添加了慢度,是因为
v1.name
过滤器为跨积联接中的每一行添加了一些固定的操作集

一个更有效的操作是检查
v1.name v2.name
,但随后会得到重复的结果,例如
(A,B),(B,A)
。然后,我们可以将
v1.name
添加回
WHERE
子句中,该子句将删除重复项,并希望由于简化的过滤器而减少行数

试试这个:

CREATE OR REPLACE VIEW vote_pairs AS
    SELECT
        v1.name as name1,
        v2.name as name2
    FROM votes AS v1
    JOIN votes AS v2
        ON v1.topic_id = v2.topic_id AND v1.name <> v2.name
    WHERE v1.name < v2.name;
创建或替换视图投票对作为
挑选
v1.name作为名称1,
v2.name作为名称2
投票结果为v1
以v2的身份加入投票
在v1.topic_id=v2.topic_id和v1.name v2.name上
其中v1.name

(编辑:似乎整理“C”
是一种方法,但我会留下这个答案,因为这是一个减少行暴露于慢速操作的好方法。)

是的,文本比较有时很慢。您可能想试试:

SELECT * FROM vote_pairs WHERE name1 > name2 collate "C";

这应该更快一些,因为它没有考虑特定于语言环境的比较规则。此外,解释分析结果表明共享缓冲区可能设置得太低。

能否提供表的架构以及
解释分析的结果?确定,已添加。此外,我在《纽约时报》上撒了一点谎——事实证明,其中一些时间会用到其他查询上。但是这里的比率仍然是1.5秒和7秒,我不禁想,基本表的结构是问题的根本原因。首先,它没有钥匙。其次,没有明确的理由说明为什么在主题id上加入它是有意义的。结果似乎只是名字或选票的笛卡尔乘积?我想知道处理与筛选器连接的方式是否需要更多内存。你能试着提高工作效率吗?我知道这不是一个真正的解决方案,但如果它有帮助,它可能是一个线索,什么是错误的。值得一看好!这确实有点帮助-它将运行时间从~7秒减少到~4秒…但这仍然比没有比较的情况慢得多。哇!这就做到了——添加
collate
可以使查询的速度与不带比较的查询的速度相同(近似)。谢谢如果要执行此操作,可能应该在
name
列上添加
CHECK
约束,将其限制在(几乎-argh,Shift-JIS)编码常见的7位ASCII字符范围内。如果应用程序不能接受,那么
C
collation可能也不会接受。谢谢你的建议。不过,在这种情况下,这并不是一个成熟的应用程序……只是一些一次性的数据分析。但我以后会记住这一点。
CREATE OR REPLACE VIEW vote_pairs AS
    SELECT
        v1.name as name1,
        v2.name as name2
    FROM votes AS v1
    JOIN votes AS v2
        ON v1.topic_id = v2.topic_id AND v1.name <> v2.name
    WHERE v1.name < v2.name;
SELECT * FROM vote_pairs WHERE name1 > name2 collate "C";