- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
(警告道歉和骇客入侵...)
背景:
我有一个遗留应用程序,我想避免重写它的大量 SQL 代码。我正在尝试加快它执行的特定类型的非常昂贵的查询(即:容易实现的成果)。
它有一个由 transactions
表表示的财务交易分类帐。当插入新行时,触发函数(此处未显示)为给定实体结转新余额。
某些类型的交易模型外部性(如机上支付)通过使用“相关”交易标记新交易,以便应用程序可以将相关交易组合在一起。
\d transactions
Table "public.transactions"
Column | Type | Modifiers
---------------------+-----------+-----------
entityid | bigint | not null
transactionid | bigint | not null default nextval('tid_seq')
type | smallint | not null
status | smallint | not null
related | bigint |
amount | bigint | not null
abs_amount | bigint | not null
is_credit | boolean | not null
inserted | timestamp | not null default now()
description | text | not null
balance | bigint | not null
Indexes:
"transactions_pkey" PRIMARY KEY, btree (transactionid)
"transactions by entityid" btree (entityid)
"transactions by initial trans" btree ((COALESCE(related, transactionid)))
Foreign-key constraints:
"invalid related transaction!" FOREIGN KEY (related)
REFERENCES transactions(transactionid)
在我的测试数据集中,我有:
因此,大约 1/3 的交易行是与某个早期交易“相关”的更新。生产数据大约是 transactionid
的 25 倍,distinct entityid
的大约 8 倍,1/3 的比例用于交易更新。
该代码查询一个特别低效的 VIEW,它被定义为:
CREATE VIEW collapsed_transactions AS
SELECT t.entityid,
g.initial,
g.latest,
i.inserted AS created,
t.inserted AS updated,
t.type,
t.status,
t.amount,
t.abs_amount,
t.is_credit,
t.balance,
t.description
FROM ( SELECT
COALESCE(x.related, x.transactionid) AS initial,
max(x.transactionid) AS latest
FROM transactions x
GROUP BY COALESCE(x.related, x.transactionid)
) g
INNER JOIN transactions t ON t.transactionid = g.latest
INNER JOIN transactions i ON i.transactionid = g.initial;
典型的查询采用以下形式:
SELECT * FROM collapsed_transactions WHERE entityid = 204425;
如您所见,where entityid = 204425
子句不会用于约束 GROUP BY
子查询,因此所有 entitids ' 事务将被分组,导致 55,000 个更大的子查询结果集和愚蠢地更长的查询时间......在撰写本文时,所有这些都平均达到 40 行(本例中为 71 行)。
我无法进一步规范化 transactions
表(比如让 initial_transactions
和 updated_transactions
表由 related
) 无需重写数百个代码库的 SQL 查询,其中许多查询以不同的方式使用自连接语义。
洞察力:
我最初尝试使用 WINDOW 函数重写查询,但是当我看到 www_fdw 时遇到了各种各样的问题(另一个 SO 问题)。将其 WHERE 子句作为 GET/POST 参数传递给 HTTP,我对无需太多重组即可优化非常幼稚的查询的可能性感到非常感兴趣。
F.31.4. Remote Query Optimization
postgres_fdw attempts to optimize remote queries to reduce the amount of data transferred from foreign servers. This is done by sending query WHERE clauses to the remote server for execution, and by not retrieving table columns that are not needed for the current query. To reduce the risk of misexecution of queries, WHERE clauses are not sent to the remote server unless they use only built-in data types, operators, and functions. Operators and functions in the clauses must be IMMUTABLE as well.
The query that is actually sent to the remote server for execution can be examined using EXPLAIN VERBOSE.
尝试:
所以我认为也许我可以将 GROUP-BY 放入一个 View 中,将该 View 视为一个外部表,并且优化器将通过 WHERE 子句传递到该外部表,从而产生更高效的查询...... .
CREATE VIEW foreign_transactions_grouped_by_initial_transaction AS
SELECT
entityid,
COALESCE(t.related, t.transactionid) AS initial,
MAX(t.transactionid) AS latest
FROM transactions t
GROUP BY
t.entityid,
COALESCE(t.related, t.transactionid);
CREATE FOREIGN TABLE transactions_grouped_by_initial_transaction
(entityid bigint, initial bigint, latest bigint)
SERVER local_pg_server
OPTIONS (table_name 'foreign_transactions_grouped_by_initial_transaction');
EXPLAIN ANALYSE VERBOSE
SELECT
t.entityid,
g.initial,
g.latest,
i.inserted AS created,
t.inserted AS updated,
t.type,
t.status,
t.amount,
t.abs_amount,
t.is_credit,
t.balance,
t.description
FROM transactions_grouped_by_initial_transaction g
INNER JOIN transactions t on t.transactionid = g.latest
INNER JOIN transactions i on i.transactionid = g.initial
WHERE g.entityid = 204425;
效果非常好!
Nested Loop (cost=100.87..305.05 rows=10 width=116)
(actual time=4.113..16.646 rows=71 loops=1)
Output: t.entityid, g.initial, g.latest, i.inserted,
t.inserted, t.type, t.status, t.amount, t.abs_amount,
t.balance, t.description
-> Nested Loop (cost=100.43..220.42 rows=10 width=108)
(actual time=4.017..10.725 rows=71 loops=1)
Output: g.initial, g.latest, t.entityid, t.inserted,
t.type, t.status, t.amount, t.abs_amount, t.is_credit,
t.balance, t.description
-> Foreign Scan on public.transactions_grouped_by_initial_transaction g
(cost=100.00..135.80 rows=10 width=16)
(actual time=3.914..4.694 rows=71 loops=1)
Output: g.entityid, g.initial, g.latest
Remote SQL:
SELECT initial, latest
FROM public.foreign_transactions_grouped_by_initial_transaction
WHERE ((entityid = 204425))
-> Index Scan using transactions_pkey on public.transactions t
(cost=0.43..8.45 rows=1 width=100)
(actual time=0.023..0.035 rows=1 loops=71)
Output: t.entityid, t.transactionid, t.type, t.status,
t.related, t.amount, t.abs_amount, t.is_credit,
t.inserted, t.description, t.balance
Index Cond: (t.transactionid = g.latest)
-> Index Scan using transactions_pkey on public.transactions i
(cost=0.43..8.45 rows=1 width=16)
(actual time=0.021..0.033 rows=1 loops=71)
Output: i.entityid, i.transactionid, i.type, i.status,
i.related, i.amount, i.abs_amount, i.is_credit,
i.inserted, i.description, i.balance
Index Cond: (i.transactionid = g.initial)
Total runtime: 20.363 ms
问题:
但是,当我尝试将其烘焙到 VIEW 中(有或没有另一层 postgres_fdw
)时,查询优化器似乎没有通过 WHERE 子句:-(
CREATE view collapsed_transactions_fast AS
SELECT
t.entityid,
g.initial,
g.latest,
i.inserted AS created,
t.inserted AS updated,
t.type,
t.status,
t.amount,
t.abs_amount,
t.is_credit,
t.balance,
t.description
FROM transactions_grouped_by_initial_transaction g
INNER JOIN transactions t on t.transactionid = g.latest
INNER JOIN transactions i on i.transactionid = g.initial;
EXPLAIN ANALYSE VERBOSE
SELECT * FROM collapsed_transactions_fast WHERE entityid = 204425;
结果:
Nested Loop (cost=534.97..621.88 rows=1 width=117)
(actual time=104720.383..139307.940 rows=71 loops=1)
Output: t.entityid, g.initial, g.latest, i.inserted, t.inserted, t.type,
t.status, t.amount, t.abs_amount, t.is_credit, t.balance,
t.description
-> Hash Join (cost=534.53..613.66 rows=1 width=109)
(actual time=104720.308..139305.522 rows=71 loops=1)
Output: g.initial, g.latest, t.entityid, t.inserted, t.type,
t.status, t.amount, t.abs_amount, t.is_credit, t.balance,
t.description
Hash Cond: (g.latest = t.transactionid)
-> Foreign Scan on public.transactions_grouped_by_initial_transaction g
(cost=100.00..171.44 rows=2048 width=16)
(actual time=23288.569..108916.051 rows=3705600 loops=1)
Output: g.entityid, g.initial, g.latest
Remote SQL:
SELECT initial, latest
FROM public.foreign_transactions_grouped_by_initial_transaction
-> Hash (cost=432.76..432.76 rows=142 width=101)
(actual time=2.103..2.103 rows=106 loops=1)
Output:
t.entityid, t.inserted, t.type, t.status, t.amount,
t.abs_amount, t.is_credit, t.balance, t.description,
t.transactionid
Buckets: 1024 Batches: 1 Memory Usage: 14kB
-> Index Scan using "transactions by entityid"
on public.transactions t
(cost=0.43..432.76 rows=142 width=101)
(actual time=0.049..1.241 rows=106 loops=1)
Output: t.entityid, t.inserted, t.type, t.status,
t.amount, t.abs_amount, t.is_credit,
t.balance, t.description, t.transactionid
Index Cond: (t.entityid = 204425)
-> Index Scan using transactions_pkey on public.transactions i
(cost=0.43..8.20 rows=1 width=16)
(actual time=0.013..0.018 rows=1 loops=71)
Output: i.entityid, i.transactionid, i.type, i.status, i.related,
i.amount, i.abs_amount, i.is_credit, i.inserted, i.description,
i.balance
Index Cond: (i.transactionid = g.initial)
Total runtime: 139575.140 ms
如果我可以将该行为嵌入到 VIEW 或 FDW 中,那么我只需在极少数查询中替换 VIEW 的 name 即可使其更加高效。我不在乎它对于其他一些用例(更复杂的 WHERE 子句)是否超慢,我将命名 VIEW 以反射(reflect)其预期用途。
use_remote_estimate
的默认值为 FALSE
,但这两种方式都没有区别。
问题:
我可以使用一些技巧来使这个公认的 hack 工作吗?
最佳答案
如果我没有正确理解您的问题,答案是“否”。没有任何“技巧”可以让额外的 where 子句通过 fdw 包装器传递。
但是,我认为您优化的可能是错误的。
我将替换整个 collapsed_transactions
View 。除非我遗漏了什么,否则它只取决于交易表。创建一个表,使用触发器对其进行更新,并且只向普通用户授予 SELECT 权限。从 pgtap 获取一些测试工具如果您还没有,那么您可以开始了。
编辑: View 优化。
如果您只想针对 View 优化该查询,并且可以调整 View 的定义,请尝试以下操作:
CREATE VIEW collapsed_transactions AS
SELECT
g.entityid, -- THIS HERE
g.initial,
g.latest,
i.inserted AS created,
t.inserted AS updated,
t.type,
t.status,
t.amount,
t.abs_amount,
t.is_credit,
t.balance,
t.description
FROM (
SELECT
entityid, -- THIS HERE
COALESCE(x.related, x.transactionid) AS initial,
max(x.transactionid) AS latest
FROM transactions x
GROUP BY entityid, COALESCE(x.related, x.transactionid)
) g
INNER JOIN transactions t ON t.transactionid = g.latest
INNER JOIN transactions i ON i.transactionid = g.initial;
请注意,子查询公开了 entityid 并允许我们对其进行过滤。我假设 entityid 对于主要项目和相关项目是不变的,否则我看不到查询如何工作。这应该让计划者对问题有足够的把握,以便首先在 entityid 上使用索引并将查询时间缩短到毫秒。
关于postgresql - 使用 postgres_fdw 加速包含多个自连接的 View ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26501327/
我想在我的 iPhone 应用程序中加入线性回归。经过一些搜索,我发现 Accelerate Framework 中的 LAPACK 和 BLAS 是正确的库。但是我很难将加速框架添加到我的 XCod
有什么方法可以加速 JS 脚本(我指的是一些复杂的 DOM 操作,比如游戏或动画)? 最佳答案 真的没有办法真正加快速度。您可以压缩它,但不会快很多。 关于Javascript 加速?,我们在Stac
有时,我必须为一个项目重新导入数据,从而将大约 360 万行读入 MySQL 表(目前是 InnoDB,但我实际上并不局限于这个引擎)。 “加载数据文件...”已被证明是最快的解决方案,但它有一个权衡
在尝试计算加速时,我被卡住了。所以给出的问题是: 问题 1 如果程序的 50% 增强了 2 倍,其余 50% 增强了 4 倍,那么由于增强而导致的整体加速是多少? Hints:考虑增强前(未增强)机器
目前我正在处理实时绘图,但可视化非常慢。我想知道你可以做些什么来加速 Matplotlib 中的事情: 后端如何影响性能?是否有后端 实时绘图比其他人更好吗? 我可以降低分辨率以提高 FPS 吗? 如
我有一个小型测试框架。它执行一个循环,执行以下操作: 生成一个小的 Haskell 源文件。 使用 runhaskell 执行此操作.该程序生成各种磁盘文件。 处理刚刚生成的磁盘文件。 这种情况发生了
这是我的网站:Instant-YouTube 如您所见,加载需要很长时间。在 IE8 及以下甚至有时会导致浏览器崩溃。我不确定是什么原因造成的。可能是 Clicksor 广告,但我认为是 swfobj
是否可以加速 SKSpriteNode? 我知道可以使用 node.physicsBody.velocity 轻松设置速度但是设置它的加速度有多难? 最佳答案 从牛顿第二定律倒推运动:F = m.a您
有没有人有加速 FCKEditor 的技术?是否有一些关键的 JavaScript 文件可以缩小或删除? 最佳答案 在最新版本 (3.0.1) 中,FCKEditor 已重命名为 CKEditor .
我有以下 MySQL 查询,需要一天多的时间才能执行: SELECT SN,NUMBER FROM a WHERE SN IN (SELECT LOWER_SN FROM b WHER
我现在正在开发一款使用加速来玩的游戏。我找到了如何让我的元素移动,但不改变它的“原点”,或者更准确地说,改变加速度计算的原点: 事实上,我的图像是移动的,它的中心是这样定义的: imageView.c
我有一个 mysql 表,其中存储有 4 列的成员消息: message_id(主键,自增) sender_id( key ) receiver_id( key ) 消息内容 我做了很多 SELECT
我在 cuda_computation.cu 中有以下代码 #include #include #include #include void checkCUDAError(const char
我正在使用 BeautifulSoup 在 for 循环中解析数千个网站。这是我的代码片段: def parse_decision(link): t1 = time.time() de
我正在使用 OpenCV 2.4 (C++) 在灰度图像上进行寻线。这涉及一些基本的图像处理步骤,如模糊、阈值、Canny 边缘检测器、梯度滤波器或霍夫变换。我必须在数千张图像上应用寻线算法。 考虑到
当我试图连续生成四次相同的报告时,我刚刚分析了我的报告应用程序。第一个用了 1859 毫秒,而后面的只用了 400 到 600 毫秒。对此的解释是什么?我能以某种方式使用它来使我的应用程序更快吗?报告
当我打开 Storyboard文件时,由于其中包含的 VC 数量,打开它需要 1-2 分钟。加快速度的最佳做法是什么?我们应该将一些 VC 移动到不同的 Storyboard文件中吗?我们是否应该使用
我有一个包含多个页面的 UIPageViewController。每个页面都是相同的 View Controller ,但会跟踪页码并显示 PDF 的正确页面。问题是每个 PDF 页面都需要在 cur
这实际上是两个问题,但它们非常相似,为了简单起见,我想将它们放在一起: 首先:给定一个已建立的 Java 项目,除了简单的代码内优化之外,还有哪些不错的方法可以加快它的速度? 其次:在用Java从头写
我有一个包含 1000 个条目的文档,其格式类似于:
我是一名优秀的程序员,十分优秀!