PostgresSQL 9.2 kullanıyorum ve yaklaşık 6.700.000 satırla 12 sütun ilişkisine sahibim. Her biri bir kullanıcıya (onu yaratan) referans veren 3B alanda düğümler içerir. Hangi kullanıcının kaç tane düğüm yarattığını sorgulamak için aşağıdakileri yapıyorum ( explain analyze
daha fazla bilgi için eklendi ):
EXPLAIN ANALYZE SELECT user_id, count(user_id) FROM treenode WHERE project_id=1 GROUP BY user_id;
QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------
HashAggregate (cost=253668.70..253669.07 rows=37 width=8) (actual time=1747.620..1747.623 rows=38 loops=1)
-> Seq Scan on treenode (cost=0.00..220278.79 rows=6677983 width=8) (actual time=0.019..886.803 rows=6677983 loops=1)
Filter: (project_id = 1)
Total runtime: 1747.653 ms
Gördüğünüz gibi, bu işlem yaklaşık 1.7 saniye sürüyor. Veri miktarı düşünüldüğünde bu fena değil, ama bunun iyileştirilip geliştirilemeyeceğini merak ediyorum. Kullanıcı sütununa bir BTree dizini eklemeye çalıştım, ancak bu hiçbir şekilde yardımcı olmadı.
Alternatif önerileriniz var mı?
Bütünlük uğruna, bu, tüm endeksleriyle (yabancı anahtar kısıtlamaları, referanslar ve tetikleyiciler olmadan) tam tablo tanımıdır:
Column | Type | Modifiers
---------------+--------------------------+------------------------------------------------------
id | bigint | not null default nextval('concept_id_seq'::regclass)
user_id | bigint | not null
creation_time | timestamp with time zone | not null default now()
edition_time | timestamp with time zone | not null default now()
project_id | bigint | not null
location | double3d | not null
reviewer_id | integer | not null default (-1)
review_time | timestamp with time zone |
editor_id | integer |
parent_id | bigint |
radius | double precision | not null default 0
confidence | integer | not null default 5
skeleton_id | bigint |
Indexes:
"treenode_pkey" PRIMARY KEY, btree (id)
"treenode_id_key" UNIQUE CONSTRAINT, btree (id)
"skeleton_id_treenode_index" btree (skeleton_id)
"treenode_editor_index" btree (editor_id)
"treenode_location_x_index" btree (((location).x))
"treenode_location_y_index" btree (((location).y))
"treenode_location_z_index" btree (((location).z))
"treenode_parent_id" btree (parent_id)
"treenode_user_index" btree (user_id)
Düzenleme: Bu, @ypercube tarafından önerilen sorguyu (ve dizini) kullandığımda ortaya çıkan sonuçtur (sorgu olmadan yaklaşık 5,3 saniye sürer EXPLAIN ANALYZE
):
EXPLAIN ANALYZE SELECT u.id, ( SELECT COUNT(*) FROM treenode AS t WHERE t.project_id=1 AND t.user_id = u.id ) AS number_of_nodes FROM auth_user As u;
QUERY PLAN
----------------------------------------------------------------------------------------------------------------------------------------------------------
Seq Scan on auth_user u (cost=0.00..6987937.85 rows=46 width=4) (actual time=29.934..5556.147 rows=46 loops=1)
SubPlan 1
-> Aggregate (cost=151911.65..151911.66 rows=1 width=0) (actual time=120.780..120.780 rows=1 loops=46)
-> Bitmap Heap Scan on treenode t (cost=4634.41..151460.44 rows=180486 width=0) (actual time=13.785..114.021 rows=145174 loops=46)
Recheck Cond: ((project_id = 1) AND (user_id = u.id))
Rows Removed by Index Recheck: 461076
-> Bitmap Index Scan on treenode_user_index (cost=0.00..4589.29 rows=180486 width=0) (actual time=13.082..13.082 rows=145174 loops=46)
Index Cond: ((project_id = 1) AND (user_id = u.id))
Total runtime: 5556.190 ms
(9 rows)
Time: 5556.804 ms
Düzenleme 2: Bu, @ erwin-brandstetter'ın önerdiği şekilde bir index
açık project_id, user_id
(ancak henüz şema optimizasyonu yok) kullandığımda ortaya çıkan sonuçtur (sorgu, orijinal sorgunla aynı hızda 1.5 saniye boyunca çalışır):
EXPLAIN ANALYZE SELECT user_id, count(user_id) as ct FROM treenode WHERE project_id=1 GROUP BY user_id;
QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------
HashAggregate (cost=253670.88..253671.24 rows=37 width=8) (actual time=1807.334..1807.339 rows=38 loops=1)
-> Seq Scan on treenode (cost=0.00..220280.62 rows=6678050 width=8) (actual time=0.183..893.491 rows=6678050 loops=1)
Filter: (project_id = 1)
Total runtime: 1807.368 ms
(4 rows)
project_id
ve user_id
? Tablo sürekli güncelleniyor mu yoksa somutlaştırılmış bir görünümle (bir süre için) çalışabilir misiniz?
Users
ileuser_id
birincil anahtar olarak?