我正在使用 Amazon RDS 上托管的 Postgres 数据仓库。当尝试从同一数据库中的另一个表更新事实表的一列(2500 万行)时,查询需要几天时间才能运行。为什么会发生这种情况,我该如何提高这种性能?我知道 PG 是为 OLTP 而设计的,而不是 OLAP,但是在这个表上选择查询性能通常相当不错。
有问题的查询如下所示:
UPDATE a
SET a.value = b.value
FROM b
WHERE a.id = b.id
Run Code Online (Sandbox Code Playgroud)
b是不同架构中的临时表,但与a. 两个表在 上都有主键id。value列上没有索引或约束。有依赖于表a但没有外键的视图
我在 RDS 上使用 PG 9.5。具有 256 GB 存储空间的通用型 (SSD),因此在用尽我们最初的突发 IOPS 后,我的 IOPS 应该会略低于 800。
IOPS 节流真的是这里的问题吗?在观看查询运行时,我看到写入性能约为 400 IOPS,读取性能类似。25,000,000 行 / 400 IOPS = 17 小时,但此查询的运行时间比 24 小时长得多(大约 30 小时后取消以尝试进行调整)。同一个表上还有其他一些定期更新流量,但是当我看到这个查询花费了多长时间时,我在大约 20 小时时停止了它。
我想知道我的一般更新方法是否错误,或者是否有使用 postgres 操作数据仓库(OLAP 工作负载)的一般建议。我能否通过放弃 RDS 并在 EC2 上运行 PG 来获得更好的性能?
更新:受回复和评论的启发,我对 45k …
postgresql performance data-warehouse update amazon-rds postgresql-performance
我有几个结构完全相同的表,我需要更新所有表中的值。
为此,我尝试构建以下脚本:
DO
$do$
DECLARE
i pg_tables%rowtype;
BEGIN
FOR i IN SELECT * FROM pg_catalog.pg_tables where schemaname like 'public' and tablename like '%_knex_migrations'
LOOP
UPDATE i.tablename SET name = replace(name, '.js', '.ts');
END LOOP;
END
$do$;
Run Code Online (Sandbox Code Playgroud)
我可以看到它i.tablename具有正确的值(我插入到 tmp 表中进行检查),但更新失败。
name: error
length: 223
severity: ERROR
code: 42P01
internalPosition: 8
internalQuery: UPDATE i."tablename" SET name = replace(name, '.js', '.ts')
where: PL/pgSQL function inline_code_block line 7 at SQL statement
file: parse_relation.c
line: 965
routine: parserOpenTable
Run Code Online (Sandbox Code Playgroud)
只是声明i.tablename上的插件UPDATE不起作用。 …
VARCHAR(32)假设我在 mySQL 数据库中有一个类型的列。
9 月 1 日,我决定存储该字符串"tea",但 9 月 2 日,我决定将其更新为"coffee".
显然,如果该表中的所有记录都相互挤压,并且我们尝试将一条记录加长 3 个字节,那么该记录之后出现的所有记录都需要向下移动 3 个字节。当然,这是荒谬的;任何 DBMS 都不可能转移数千个可能的条目。
那么mySQL 在这种情况下到底会做什么呢?对于 TEXT 和 BLOB 类型,它的行为方式是否相同?
编辑: 一天后读完这篇文章后,我意识到这个问题相当模糊。这是一个我希望能够澄清问题的例子:
假设我有一个表,fav_drinks有两列:
user_id,这是一个INTEGERdrink,这是一个VARCHAR(32)假设这个表在内存中是这样存储的:
[1,"juice",2,"tea",3,"soda",4,"hot chocolate"]
Run Code Online (Sandbox Code Playgroud)
也就是说,所有记录都按顺序存储。如果我们需要将用户 2 最喜欢的饮料从 更新为"tea","coffee"理论上我们需要将用户 3 和 4 的条目下移。当然,我不认为这在真实的数据库中会发生。
那么,重申一下这个问题,mySQL 如何管理一个表条目突然需要更多内存的这种特定情况?
后续问题:
我们如何在并行、多线程环境中删除和重新插入行,同时避免竞争条件、死锁等?我们仍然使用 ( UPDLOCK, SERIALIZABLE) 或其他锁吗?
我们有两个表:Order和OrderLineDetail。表Order是存储一般信息的父级;和OrderLineDetail是子表,因为订单有多个明细行项目。
订单可以更新,所以我们首先检查OrderId表中是否存在,并相应地插入或更新。
由于客户修改、线路问题、服务器繁忙等,订单文件可以多次发送。我们有一个时间Lastfiledatetime栏。如果传入的时间戳较旧,则对表没有影响。
对于OrderLineDetail表,有时我们的文件中没有自然键或代理键,因此我们删除所有子OrderLineDetail项,然后重新填充(这是一个较旧的遗留系统的 xml 文件)。
Create Table Orders
(OrderId bigint primary key, -- this is in xml files
Lastfiledatetime datetime null
)
Create Table OrderLineDetail
(OrderLineDetailid bigint primary key identity(1,1), -- this is Not in the xml files
OrderLineDescription varchar(50),
OrderLineQuantity int,
OrderId bigint foreign key references Orders(OrderId),
Lastfiledatetime datetime
) …Run Code Online (Sandbox Code Playgroud) 我有下表fields:
+----------+---------+-----------------+-------------+---------+--------------+---------------+-----------+------------------------------+-------------+------------------+
| field_id | form_id | form_section_id | is_required | grid_id | is_base_grid | field_type_id | field_seq | field_name | field_class | field_class_data |
+----------+---------+-----------------+-------------+---------+--------------+---------------+-----------+------------------------------+-------------+------------------+
| 220481 | 9926 | NULL | 0 | NULL | NULL | 4 | 28 | Test | NULL | NULL |
| 281863 | 9926 | NULL | 0 | NULL | NULL | 10 | 29 | insert after yes no question | NULL | NULL |
| 220496 …Run Code Online (Sandbox Code Playgroud) 我创建了一个 varbinary 哈希来检查 2 个表之间的更改。
这是执行计划,我对索引有点困惑,或者确实有更好的编写方式。 https://www.brentozar.com/pastetheplan/?id=HkHmqoczm
连接中的 2 列是目标中的 PK,并且在源中具有非聚集索引。困扰我的一点是排序导致的 tempdb 溢出。
鉴于这种
declare @Data table (id int, fact char(1));
declare @Summary table (id int, collected varchar(99));
insert @Data(id, fact)
values
(1, 'a'),
(1, 'b'),
(2, 'c'),
(2, 'd'),
(2, 'e');
-- Form a list of unique id values
insert @Summary(id, collected) select distinct id, '' from @Data;
-- Accumulate the fact values into collected
update s
set collected = collected + d.fact
from @Summary as s
inner join @Data as d
on d.id = s.id;
select * from @Summary;
Run Code Online (Sandbox Code Playgroud)
我曾预料
id …Run Code Online (Sandbox Code Playgroud) 我先说这是来自 Stack Overflow 上一个未回答问题的交叉帖子。
我这样做并不是为了获得对这个问题的更多看法,我希望 DBA 社区分享他们对这是否可能是 SQL Server 中的错误的看法。我认为 SO 社区没有专业知识来决定这一点,所以我在这里重新发布。
假设我有一个 table T,并且我有一个索引视图V:
CREATE TABLE dbo.T (id int PRIMARY KEY, b bit NOT NULL, txt varchar(20));
GO
CREATE VIEW dbo.V
WITH SCHEMABINDING AS
SELECT T.Id, T.txt
FROM dbo.T AS T
WHERE T.b = 1;
GO
CREATE UNIQUE CLUSTERED INDEX idx_V ON dbo.V (Id);
Run Code Online (Sandbox Code Playgroud)
在这个简单的例子中,它基本上只是一个过滤索引,但它也可以有连接等。
我现在想在Twhere 中选择一些行,这里b = 1的过滤视图非常有用,我在标准上所以必须使用NOEXPAND(或者它对于视图匹配来说太复杂了):
SELECT Id, txt
FROM V WITH (NOEXPAND);
Run Code Online (Sandbox Code Playgroud)
这很好用。
现在我想将这些行更新为某个值。该视图符合可更新条件,因此我可以执行以下操作: …
我最近开始将个人项目从 Microsoft SQL Server 转换为 PostgreSQL,我对UPDATE JOIN在两个表之间执行时遇到的糟糕性能感到惊讶。
假设它们看起来像:
CREATE TABLE foo (
id INTEGER NOT NULL PRIMARY KEY,
bar INTEGER NULL
);
CREATE TABLE foo2 (
id INTEGER NOT NULL PRIMARY KEY,
bar INTEGER NULL
);
Run Code Online (Sandbox Code Playgroud)
在 T-SQL 中,我会使用这样的连接来进行更新:
UPDATE foo
SET bar = t2.bar
FROM foo t1
JOIN foo2 t2
ON t1.id = t2.id;
Run Code Online (Sandbox Code Playgroud)
但是在 Postgres 中运行,查询速度非常慢。
如果我将其更改为:
UPDATE foo
SET bar = t2.bar
FROM foo2 t2
WHERE foo.id = t2.id;
Run Code Online (Sandbox Code Playgroud)
这不是问题。
我知道语法是不同的,但我希望查询优化器能在同一个球场上解决一些问题。相反,事情变得疯狂。除了语法差异之外,我看不到的两个查询之间是否存在细微差别?
Update on foo …Run Code Online (Sandbox Code Playgroud) 我只是想了解为什么会发生这种情况,而我的 Google 搜索失败了。我们使用的是 SQL Server 2016 SP1。
这是这种情况:供应商表通过跟踪每个表的当前值来管理 ID。如果您正在执行插入操作,则可以调用一个函数来返回一个 ID 块。
因此,我们通过使用从真实表中选择来设置临时表select into(我们正在克隆一组数据,以使用不同的属性集重新插入)。
然后我们调用该函数并获取记录数的新 id(它只返回最大 ID,因此我们进行一些数学运算以获取下一个 id)。
然后我们更新表格:
update #temp set @nextId = Id = @nextId + 1
Run Code Online (Sandbox Code Playgroud)
期望它会为每条记录递增 1 并设置 id。
相反,为每 4 条记录设置相同的 ID,然后它会递增,接下来的 4 条会得到下一个 id,等等。为什么每 4 条记录?什么地方出了错?
更有趣的是,如果我们在表上放置一个聚集索引,一切都会正常进行。
我确定这与表是堆有关……但不知道为什么。
update ×10
sql-server ×7
postgresql ×3
amazon-rds ×1
concurrency ×1
ddl ×1
dynamic-sql ×1
heap ×1
join ×1
mysql ×1
performance ×1
plpgsql ×1
query ×1
t-sql ×1
varchar ×1