sql - 如何优化结合了 INNER JOIN、DISTINCT 和 WHERE 的 SQL 查询?
问题描述
SELECT DISTINCT options.id, options.foo_option_id, options.description
FROM vehicles
INNER JOIN vehicle_options ON vehicle_options.vehicle_id = vehicles.id
INNER JOIN options ON options.id = vehicle_options.option_id
INNER JOIN discounted_vehicles ON vehicles.id = discounted_vehicles.vehicle_id
WHERE discounted_vehicles.discount_id = 4;
上面的查询返回 2067 行,它在 1.7 秒内在本地运行。我想知道它是否尽可能快,或者我是否可以以某种方式进一步调整它,因为这个数据集会随着时间的推移快速增长。
我在没有改变速度的情况下尝试过的事情:
1 - 更改连接顺序,从最小的表连接到最大的表。
2 - 向 discounted_vehicles.discount_id 添加索引。
解决方案
最佳查询取决于缺失的信息。
在典型设置中,这应该会更快:
SELECT id, foo_option_id, description
FROM options o
WHERE EXISTS (
SELECT
FROM discounted_vehicles d
JOIN vehicle_options vo USING (vehicle_id)
WHERE d.discount_id = 4
AND vo.option_id = o.id
);
假设参照完整性,由 FK 约束强制执行,我们可以从查询中省略表vehicle
并直接连接 from discounted_vehicles
to vehicle_options
。
此外,EXISTS
如果每个不同选项有许多符合条件的行,通常会更快。
理想情况下,您将在以下位置拥有多列索引:
discounted_vehicles(discount_id, vehicle_id)
vehicle_options(vehicle_id, option_id)
按此顺序索引列。您可能对vehicle_options
提供第二个索引有 PK 约束,但列顺序应该匹配。有关的:
根据实际数据分布,可能会有更快的查询样式。有关的:
更改连接顺序通常是徒劳的。Postgres 重新排序以任何它期望最快的方式加入。(有例外情况。)相关:
推荐阅读
- python - odoo 13:write() 函数更新错误记录
- android - 在以下任何来源中均未找到插件 [id: 'com.google.gms.google-services']:
- angular - 如何在没有后端的角度项目中实现 .htaccess 文件
- javascript - 根据用户权限渲染部分视图
- python - tsfresh 时间序列特征提取
- azure - 如何自动化 Azure Web 应用程序部署以从 azure 容器中选择最新图像
- flutter - 我在哪里可以看到颤振 Windows 日志?
- java - 基本身份验证和 Java Swing - 如何
- c# - KafkaConsumer 在检索消息时永远挂起
- powershell - 对象作为变量