我有一个数据库表,有接近 100 列 - 25 列是 STRING,其余是 INT/DECIMAL/BOOL。
这是我尝试运行的查询 - 该查询是根据用户必须过滤表中数据的搜索条件生成的
listings
:
SELECT "listings".*
FROM "listings"
WHERE "listings"."source" = 3
AND "listings"."listing_type" = 4
ORDER BY listings.created_at DESC
LIMIT 100 OFFSET 0
此查询有多种变体,具体取决于用户选择的参数。上面的查询需要 Rails 应用程序超过 4 分钟才能响应(在生产中,它会导致蓝屏显示“出现问题...”,日志中没有错误消息):
Completed 200 OK in 244372ms (Views: 71.4ms | ActiveRecord: 244263.2ms | Allocations: 17464)
我认为可以通过在
WHERE
和 ORDER BY
子句中的列上添加索引来提高性能,但这没有任何帮助。
我还尝试在 pgAdmin 客户端中运行
EXPLAIN ANALYSE SELECT "listings".* FROM "listings" WHERE "listings"."source" = 3 AND "listings"."listing_type" = 4 ORDER BY listings.created_at DESC LIMIT 100 OFFSET 0
并得到了这个:
"Limit (cost=0.42..1903.89 rows=100 width=1587) (actual time=64960.075..170237.003 rows=8 loops=1)"
" -> Index Scan Backward using index_listings_on_created_at on listings (cost=0.42..437892.59 rows=23005 width=1587) (actual time=64960.073..170236.988 rows=8 loops=1)"
" Filter: ((source = 3) AND (listing_type = 4))"
" Rows Removed by Filter: 1022248"
"Planning Time: 25.418 ms"
"Execution Time: 170237.100 ms"
执行这个
EXPLAIN ANALYSE...
命令,花了2分51秒才得到语句。
此表中的数据工作(加载、搜索、过滤)速度缓慢,导致整个应用程序无法使用。
数据库表
listings
- id (int)
- source (int)
- title (string)
- description (text)
- listing_type (int)
- transaction_type (int)
- region (int)
- uuid (uuid)
- ...other columns...
- created_at (datetime)
- updated_at (datetime)
现有指数:
INDEX NAME INDEXDEF
listings_pkey CREATE UNIQUE INDEX listings_pkey ON
public.listings USING btree (id) index_listings_on_listing_type CREATE INDEX index_listings_on_listing_type ON public.listings USING btree (listing_type)
index_listings_on_transaction_type CREATE INDEX index_listings_on_transaction_type ON public.listings USING btree (transaction_type)
index_listings_on_region CREATE INDEX index_listings_on_region ON public.listings USING btree (region)
index_listings_on_created_at CREATE INDEX index_listings_on_created_at ON public.listings USING btree (created_at)
index_listings_on_uuid CREATE INDEX index_listings_on_uuid ON public.listings USING btree (uuid)
我可以采取哪些措施来提高其性能?
注意 - 我使用
will_paginate
进行分页,我了解到 Rails 应用程序中的一个源性能问题是分页 gem 始终运行 SELECT COUNT(*) FROM table
,这对于大表来说是一个问题。
(source, listing_type, created_at)
上的索引应该是所示查询的神奇解决方案。 不过,我不知道它会如何处理所描述的看不见的变化。
行估计偏差 23005/8 = 2875 的事实当然无助于制定稳健的计划。 你知道为什么会差这么多吗? 如果您仅分别查询源和列表类型(没有 LIMIT 和 ORDER BY),那么这些估计值是否准确?