使用索引加速使用来自不同表的值的查询
Use index to speed up query using values from different tables
我有一个 table 个产品、一个 table 个订单和一个 table 个 orderProducts。
产品的名称为 PK(苹果、香蕉、芒果)和价格。
订单有一个 created_at 日期和一个 id 作为 PK。
orderProducts 连接订单和产品,因此它们有一个 product_name 和一个 order_id。现在我想显示过去 24 小时内发生的给定产品的所有订单。
我使用以下查询:
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
这可行,但我想用索引优化此查询。该索引需要先按
排序
- 商品名,可以过滤
- 然后created_at降序排列,这样就可以select只有24小时前的
问题是,据我所知,只能在单个 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),
)
这些规则在性能方面很重要:
- 整数索引比字符串索引快,因此,您应该尽量使主键始终是整数。因为 join tables 也使用主键。
- 如果 when in where 子句总是使用两个字段,那么我们必须为这两个字段创建一个索引。
- 外键没有索引,您必须手动为外键字段创建索引。
因此,推荐的 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
我希望在两列上都看到索引,但是对于此查询,只需要一个。在实践中,您将从 products
到 orders
,或其他方式 - 两条路径都是可能的,这就是为什么我写了关于索引两列的内容。我会使用两个单独的索引:
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 本身。
我有一个 table 个产品、一个 table 个订单和一个 table 个 orderProducts。
产品的名称为 PK(苹果、香蕉、芒果)和价格。
订单有一个 created_at 日期和一个 id 作为 PK。
orderProducts 连接订单和产品,因此它们有一个 product_name 和一个 order_id。现在我想显示过去 24 小时内发生的给定产品的所有订单。
我使用以下查询:
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
这可行,但我想用索引优化此查询。该索引需要先按
排序- 商品名,可以过滤
- 然后created_at降序排列,这样就可以select只有24小时前的
问题是,据我所知,只能在单个 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),
)
这些规则在性能方面很重要:
- 整数索引比字符串索引快,因此,您应该尽量使主键始终是整数。因为 join tables 也使用主键。
- 如果 when in where 子句总是使用两个字段,那么我们必须为这两个字段创建一个索引。
- 外键没有索引,您必须手动为外键字段创建索引。
因此,推荐的 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
我希望在两列上都看到索引,但是对于此查询,只需要一个。在实践中,您将从 products
到 orders
,或其他方式 - 两条路径都是可能的,这就是为什么我写了关于索引两列的内容。我会使用两个单独的索引:
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 本身。