Performance 为PostgreSQL查询选择正确的索引
简化表格:Performance 为PostgreSQL查询选择正确的索引,performance,postgresql,indexing,postgresql-8.4,Performance,Postgresql,Indexing,Postgresql 8.4,简化表格: CREATE TABLE products ( product_no integer PRIMARY KEY, sales integer, status varchar(16), category varchar(16)); CREATE INDEX index_products_sales ON products (sales); CREATE INDEX index_products_status ON products (status); CREATE INDEX inde
CREATE TABLE products (
product_no integer PRIMARY KEY,
sales integer,
status varchar(16),
category varchar(16));
CREATE INDEX index_products_sales ON products (sales);
CREATE INDEX index_products_status ON products (status);
CREATE INDEX index_products_category ON products (category);
PostgreSQL版本是8.4。列“状态”和“类别”
有2000万种产品/行分布在15个类别中
最常用的查询之一是获得三种最畅销的产品,不包括“cat3”和“cat7”类别的产品:
SELECT product_no, sales
FROM products
WHERE status = 'something' AND category NOT IN ('cat3', 'cat7')
ORDER BY sales DESC
LIMIT 3;
Limit (cost=0.00..8833.39 rows=3 width=12) (actual time=9235.332..9356.284 rows=3 loops=1)
-> Index Scan using index_products_sales on products (cost=0.00..68935806.85 rows=23412 width=12) (actual time=9235.327..9356.278 rows=3 loops=1)
Filter: (((category)::text <> ALL ('{cat3,cat7}'::text[])) AND ((status)::text = 'something'::text))
选择产品编号、销售
来自产品
其中状态='something'和类别不在('cat3'、'cat7')
按销售说明订购
限制3;
限制(成本=0.00..8833.39行=3宽度=12)(实际时间=9235.332..9356.284行=3圈=1)
->使用产品销售索引进行索引扫描(成本=0.00..68935806.85行=23412宽度=12)(实际时间=9235.327..9356.278行=3个循环=1)
筛选器:((类别)::text ALL({cat3,cat7})::text[])和((状态)::text='something'::text))
让这个特定查询运行得更快的最佳索引是什么?我认为b树索引仍然是最好的选择。不过,我可能错了。我想我应该测试两件事 首先,不包括“cat3”和“cat7”的类别的部分索引
CREATE INDEX index_products_category ON products (category)
WHERE category NOT IN ('cat3','cat7');
第二,销售的降序排序
CREATE INDEX index_products_sales ON products (sales DESC);
但是,其中任何一个都可能会减慢其他查询的速度,因此除了现有索引之外,您可能还需要其中一个或两个索引。创建具有此特定排序顺序的部分多列索引:
CREATE INDEX products_status_sales_partial_idx ON products (status, sales DESC)
WHERE category NOT IN ('cat3','cat7');
稍微修改您的查询:
索引(status,sales DESC)
的排序顺序符合逻辑结果。因此,它将读取所有符合条件的行,排序并选择前3行
通过将status
添加到ORDER By
中,可以使查询计划器直接从索引中读取前3个条目。预计速度将提高几个数量级
使用PostgreSQL 8.4和9.1进行测试。在产品(状态、sales DESC NULLS LAST)上创建索引(类别='cat3'和类别='cat7')@jug:index的
条件在逻辑上是错误的,所有行都以这种方式限定,因为没有行可以同时匹配两个类别。我添加了一个答案。@ErwinBrandstetter:当然,你是对的。谢谢你的回答,但它真的应该在WHERE NOT子句中写“(category='cat3'和category='cat7')吗?不,不应该,我不知道为什么我一开始就写了类似WHERE子句的东西。那时我应该已经醒了<代码>类别不在('cat3','cat7')的地方。
是我通常的想法。在这里,在一个有一百万行的表上,这个过程大约在.06毫秒内完成。
SELECT product_no, sales
FROM products
WHERE status = 'something'
AND category NOT IN ('cat3', 'cat7')
ORDER BY status, sales DESC
LIMIT 3;
WHERE status = 'something' ...
ORDER BY sales DESC