使用索引加速使用来自不同表的值的查询

Use index to speed up query using values from different tables

我有一个 table 个产品、一个 table 个订单和一个 table 个 orderProducts。

我使用以下查询:

SELECT 
   orders.id, 
   orders.created_at, 
   products.name,
   products.price
FROM
   orderProducts
JOIN products ON
   products.name=orderProducts.product
JOIN orders ON
   orders.id=orderProducts.order
WHERE
      products.name='banana'
   AND
      orders.created_at BETWEEN NOW() - INTERVAL '24 HOURS' AND NOW()
ORDER BY
   orders.created_at
    

这可行,但我想用索引优化此查询。该索引需要先按

排序

问题是,据我所知,只能在单个 table 上创建索引,不可能将另一个 table 的值连接到它。由于两个单独的索引也不能解决这个问题,我想知道是否有其他方法可以优化这个特定的查询。

这是 table 脚本:

CREATE TABLE products
(
    name text PRIMARY KEY,
    price integer,

)

CREATE TABLE orders
(
    id SERIAL PRIMARY KEY,
    created_at TIMESTAMP DEFAULT NOW(),

)

CREATE TABLE orderProducts
(
    product text REFERENCES products(name),
    "order" integer REFERENCES orders(id),

)

这些规则在性能方面很重要:

  1. 整数索引比字符串索引快,因此,您应该尽量使主键始终是整数。因为 join tables 也使用主键。
  2. 如果 when in where 子句总是使用两个字段,那么我们必须为这两个字段创建一个索引。
  3. 外键没有索引,您必须手动为外键字段创建索引。

因此,推荐的 table 脚本是:

CREATE TABLE products
(
    id serial primary key, 
    name text,
    price integer
);
CREATE UNIQUE INDEX products_name_idx ON products USING btree (name);


CREATE TABLE orders
(
    id SERIAL PRIMARY KEY,
    created_at TIMESTAMP DEFAULT NOW()
);
CREATE INDEX orders_created_at_idx ON orders USING btree (created_at);


CREATE TABLE orderProducts
(
    product_id integer REFERENCES products(id),
    order_id integer REFERENCES orders(id)
);
CREATE INDEX orderproducts_product_id_idx ON orderproducts USING btree (product_id, order_id);
---- OR ----  
CREATE INDEX orderproducts_product_id ON orderproducts (product_id);
CREATE INDEX orderproducts_order_id ON orderproducts (order_id);

首先。请不要在任何地方放置索引 - 这会导致操作变化缓慢...

如@Laurenz Albe 所提议 - 不要猜测 - 检查。

除此之外。请注意,您知道产品名称,价格重复 - 因此您可以查询一次。问题是在您的情况下,两个查询是否会比单个查询更快...检查一下。

请阅读docs。我会试试这个索引:

create index orders_id_created_at on orders(created_at desc, id)

通常 id 应该排在第一位,因为它是唯一的,但是这里系统应该能够过滤掉两个谓词 - where/join。这里只是猜测。

orderProducts 我希望在两列上都看到索引,但是对于此查询,只需要一个。在实践中,您将从 productsorders,或其他方式 - 两条路径都是可能的,这就是为什么我写了关于索引两列的内容。我会使用两个单独的索引:

create index orderproducts_product_id on orderproducts (product_id) include (order_id);
create index orderproducts_order_id on orderproducts (order_id) include (product_id);

可能变化不大,但是...想法是只使用索引,而不是 table 本身。