Sql heroku上的数据库查询超时
我正在对一个应用程序进行压力测试,添加一大堆的项目,强迫它做很多工作Sql heroku上的数据库查询超时,sql,postgresql,heroku,Sql,Postgresql,Heroku,我正在对一个应用程序进行压力测试,添加一大堆的项目,强迫它做很多工作 select *, ( select price from prices WHERE widget_id = widget.id ORDER BY id DESC LIMIT 1 ) as maxprice FROM widgets ORDER BY created_at DESC LIMIT 20 OFFSET 0 该查询从窗口小部件(约8500个)中选择,其中p
select *, (
select price
from prices
WHERE widget_id = widget.id
ORDER BY id DESC
LIMIT 1
) as maxprice
FROM widgets
ORDER BY created_at DESC
LIMIT 20 OFFSET 0
- 该查询从窗口小部件(约8500个)中选择,其中prices有777000个左右的条目
我对sql和查询等大规模的世界是完全陌生的,因此我完全不懂上面所说的:) 我不太清楚你在问什么,但我的理解是: 找到您想要定价的小部件。在本例中,看起来您正在查找最近的20个小部件:
SELECT w.id
FROM widgets
ORDER BY created_at DESC
LIMIT 20 OFFSET 0
对于您找到的20个小部件中的每一个,您似乎希望从小部件表中找到最高的关联价格:
SELECT s.id, MAX(p.price) AS maxWidgetPrice
FROM (SELECT w.id
FROM widgets
ORDER BY created_at DESC
LIMIT 20 OFFSET 0
) s -- widget subset
, prices p
WHERE s.id = p.widget_id
GROUP BY s.id
prices.widget_id需要索引才能生效。如果prices表相对较大,您不希望每次都处理整个prices表,只处理所需行的子集。
编辑:在下面的评论之后添加了“分组依据”(没有,这没有经过测试)最终版本:
@Dave想要每个小部件的最新价格。您可以在子查询和每个小部件的限制1
中实现这一点,但在现代PostgreSQL中,窗口函数可以更优雅地完成这项工作。考虑:
每个小部件最高价格的原始帖子:
- 修复表别名
- 检索
小部件的所有列,如问题所示
- 在PostgreSQL 8.3中,您必须在
GROUP BY
子句中拼写出SELECT
列表的所有非聚合列。在PostgreSQL 9.1或更高版本中,主键列将覆盖整个表。我引述该手册:
在主查询时允许查询目标列表中的非GROUP BY列
密钥在GROUPBY子句中指定
- 我建议不要使用像
maxWidgetPrice
这样的工具。在PostgreSQL中,默认情况下,不带引号的标识符折叠为小写。帮自己一个忙,只使用小写标识符
- 尽可能始终使用显式连接条件。这是规范的SQL方式,更具可读性
偏移量0
只是噪音
索引:
然而,性能的关键是正确的索引。我将使用两个类似的索引:
CREATE INDEX widgets_created_at_idx ON widgets (created_at DESC);
CREATE INDEX prices_widget_id_idx ON prices(widget_id, price DESC);
第二个是,在您使用第一个索引确定前20个小部件之后,它应该为检索最大奖品提供最佳性能。不确定PostgreSQL 8.3(Heroku shared db的默认版本)是否已经足够智能,可以充分利用它。PostgreSQL 9.1当然是
对于最新价格(参见备注),请使用以下索引:
CREATE INDEX prices_widget_id_idx ON prices(widget_id, created_at DESC);
你不必(也不应该)相信我。使用索引和不使用索引测试性能和查询计划,并亲自查看。索引创建速度应该非常快,即使对于一百万行也是如此
如果您考虑切换到HeloCu上的独立PostgreSQL数据库,您可能会感兴趣:
默认值现在是PostgreSQL 9.1
您现在可以在那里取消长时间运行的查询
widget.id
是主键吗?如果没有,你有索引吗?以及在小部件\u id
?看起来价格正在更新。如果是这种情况,请在中更新它们,而不是插入。还是你需要保持原来的价格?也不要使用select*
,因为检索所有列可能会很昂贵。使用explain
了解查询中最昂贵的内容。感谢您提供详细的答案。我得到“列“w.id”必须出现在GROUPBY子句中或用于聚合函数”,如果我在GROUPBY子句中添加w.id,它会要求我将w.title添加到GROUPBY子句中,依此类推,直到添加所有小部件列。那么查询就行了!我以前见过这组人,这让我很困惑。这是9.1中不需要的吗?@dave:是的,我忘记了GROUPBY子句。请看修改后的答案。谢谢,欧文,太好了。我刚刚意识到我需要修改这个查询-getting max(price)从prices表中获取相应小部件的最高价格。我真正需要的是最后的价格。价格通过一个过程在一小时内更新,所以这就是为什么我在最初的查询中在DESC limit 1创建了order by_,但我们走在正确的轨道上,期待着稍后尝试破解这个问题。价格有点像股价,所以每个小部件都有一个随时间而涨跌的股价,所以最后的股价是最重要的,因为这是它的当前价值。@Dave:我为每个小部件添加了一个“最新价格”的解决方案。
CREATE INDEX widgets_created_at_idx ON widgets (created_at DESC);
CREATE INDEX prices_widget_id_idx ON prices(widget_id, price DESC);
CREATE INDEX prices_widget_id_idx ON prices(widget_id, created_at DESC);