我有一个带有布尔字段(“测试”)索引的表。当它为真时,它使用索引,因此加载速度很快,但当它为假时,它不使用它。有什么问题吗?
我这里有它的解释分析:
DB_development=# explain analyze SELECT COUNT(*) FROM "users" WHERE "users"."is_test" = 't';
QUERY PLAN
------------------------------------------------------------------------------------------------------------------------------------------------------
Aggregate (cost=22890.67..22890.68 rows=1 width=0) (actual time=1848.655..1848.656 rows=1 loops=1)
-> Index Scan using index_users_on_is_test on users (cost=0.00..22846.51 rows=17665 width=0) (actual time=34.727..1844.081 rows=21457 loops=1)
Index Cond: (is_test = true)
Filter: is_test
Total runtime: 1848.882 ms
(5 rows)
DB_development=# explain analyze SELECT COUNT(*) FROM "users" WHERE "users"."is_test" = 'f';
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------
Aggregate (cost=84505.74..84505.75 rows=1 width=0) (actual time=9557.632..9557.632 rows=1 loops=1)
-> Seq Scan on users (cost=0.00..84063.72 rows=176807 width=0) (actual time=71.653..9533.595 rows=219531 loops=1)
Filter: (NOT is_test)
Total runtime: 9557.655 ms
(4 rows)
更新
我在这里看到在可以忽略索引的布尔字段上添加索引...我认为这是正确的,因为与测试用户相比,非测试用户实际上相当多。
DB_development=# SELECT COUNT(*) FROM "users" WHERE "users"."is_test" = 't';
count
-------
21457
(1 row)
DB_development=# SELECT COUNT(*) FROM "users" WHERE "users"."is_test" = 'f';
count
--------
219531
(1 row)
如果是这样的话......那我怎么能快速计数呢?
更新
这是创建表和索引:
create_table "users", :force => true do |t|
t.integer "genre_id"
t.integer "country_id"
t.boolean "is_test", :default => false
t.datetime "created_at"
t.datetime "updated_at"
... + 90 more fields (it's my main table)
end
add_index "users", ["country_id"], :name => "index_users_on_country_id"
add_index "users", ["genre_id"], :name => "index_users_on_genre_id"
add_index "users", ["is_test"], :name => "index_users_on_is_test"
... + 17 more indexes