Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Performance 为PostgreSQL查询选择正确的索引_Performance_Postgresql_Indexing_Postgresql 8.4 - Fatal编程技术网

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