Saya menjalankan PostgresSQL 9.2 dan memiliki hubungan 12 kolom dengan sekitar 6.700.000 baris. Ini berisi node dalam ruang 3D, masing-masing referensi pengguna (yang membuatnya). Untuk menanyakan pengguna yang telah membuat berapa node, saya melakukan hal berikut (ditambahkan explain analyze
untuk informasi lebih lanjut):
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
Seperti yang Anda lihat, ini membutuhkan waktu sekitar 1,7 detik. Ini tidak terlalu buruk mengingat jumlah data, tetapi saya ingin tahu apakah ini dapat ditingkatkan. Saya mencoba menambahkan indeks BTree pada kolom pengguna, tetapi ini tidak membantu sama sekali.
Apakah Anda punya saran alternatif?
Demi kelengkapan, ini adalah definisi tabel lengkap dengan semua indeksnya (tanpa batasan, referensi, dan pemicu kunci asing):
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)
Sunting: Ini hasilnya, ketika saya menggunakan kueri (dan indeks) yang diajukan oleh @ypercube (kueri membutuhkan waktu sekitar 5,3 detik tanpa 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
Sunting 2: Ini adalah hasilnya, ketika saya menggunakan index
on project_id, user_id
(tapi belum ada optimasi skema, belum) seperti yang disarankan oleh @ erwin-brandstetter (kueri berjalan dengan 1,5 detik pada kecepatan yang sama dengan permintaan asli saya):
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
dan user_id
? Apakah tabel diperbarui terus menerus atau dapatkah Anda bekerja dengan tampilan yang terwujud (untuk beberapa waktu)?
Users
denganuser_id
sebagai kunci utama?