由于我是一名年轻的开发人员并且不太擅长使用数据库(PostgreSQL 9.3),因此我在项目中遇到了一些问题,我确实需要帮助。
我的项目是关于从设备(最多 1000 个或更多设备)收集数据,其中每个设备每秒发送一个数据块,每小时大约生成 300 万行。
目前我有一张大表,用于存储每个设备的传入数据:
CREATE TABLE data_block(
id bigserial
timestamp timestamp
mac bigint
)
Run Code Online (Sandbox Code Playgroud)
由于数据块可以(或不可以)包含多种类型的数据,因此还有其他表引用该data_block表。
CREATE TABLE dataA(
data_block_id bigserial
data
CONSTRAINT fkey FOREIGN KEY (data_block_id) REFERENCES data_block(id);
);
CREATE TABLE dataB(...);
CREATE TABLE dataC(...);
CREATE INDEX index_dataA_block_id ON dataA (data_block_id DESC);
...
Run Code Online (Sandbox Code Playgroud)
有可能在一个 data_block 中有 3x dataA、1x dataB,但没有 dataC。
数据将保留数周,因此该表中将有大约 50 亿行。目前,我在表中有大约 6 亿行,我的查询需要很长时间。所以我决定在timestampand上做一个索引mac,因为我的 select 语句总是随着时间的推移而查询,而且通常也随着时间+mac。
CREATE INDEX index_ts_mac ON data_block (timestamp DESC, mac);
Run Code Online (Sandbox Code Playgroud)
...但我的查询仍然需要很长时间。比如我查询了一天一台mac的数据:
SELECT * FROM data_block …Run Code Online (Sandbox Code Playgroud) 我在表上添加新列时遇到问题。
我尝试运行了几次,但是运行了 10 多分钟后,由于锁定时间,我决定取消查询。
ALTER TABLE mytable ADD mycolumn VARCHAR(50);
Run Code Online (Sandbox Code Playgroud)
有用的信息:
我发现了有关 PostgreSQL 管理可空列的方式的有趣信息(通过 HeapTupleHeader)。
我的第一个猜测是,因为这个表已经有 32 个 8 位的可空列MAXALIGN, HeapTupleHeader 是 4 字节长度(未验证,我不知道如何这样做)。
因此,添加新的可为空的列可能需要在每一行上更新 HeapTupleHeader 以添加新的 8-bits MAXALIGN,这可能会导致性能问题。
因此,我尝试更改可空列之一(实际上并不是真正可以为空的),以便将可空列的数量减少到 31,以检查我的猜测是否属实。
ALTER TABLE mytable ALTER myothercolumn SET NOT NULL;
Run Code Online (Sandbox Code Playgroud)
不幸的是,这个改动也需要很长时间,超过5分钟,所以我也中止了。
您知道是什么导致了这种性能成本吗?
我不明白 Craig Ringer 在评论时的意思:
如果插入事务回滚,此解决方案可能会丢失更新;没有强制执行 UPDATE 影响任何行的检查。
在/sf/answers/609160401/ 上。请提供一个示例事件序列(例如,线程 1 执行 X,线程 2 执行 Y)以演示丢失更新是如何发生的。
根据克雷格·林格的说法:
虽然在(或包括)引用端外键列上创建索引通常是个好主意,但这不是必需的。您添加的每个索引都会稍微减慢 DML 操作的速度,因此您需要为每个
INSERT,UPDATE或支付性能成本DELETE。如果索引很少使用,它可能不值得拥有。
您如何确定添加索引的收益是否超过其成本?
您是否在添加索引之前/之后分析单元测试并检查整体性能提升?或者,还有更好的方法?
我创建了一个 PostgresQL 表,但我在其中一列上添加了一个未命名的检查约束:
CREATE TABLE FOO
(
id serial primary key,
price_range smallint CHECK (price_range > 0),
url varchar(255)
);
Run Code Online (Sandbox Code Playgroud)
现在我想删除这个约束,但我不知道如何。典型的 ALTER TABLE...DROP CONSTRAINT... 需要一个,constraint_name但我没有。
我知道这里有一个答案,但是当我尝试按照那里的答案确定检查约束的名称时:
SELECT *
FROM information_schema.constraint_table_usage
WHERE table_name = 'your_table'
Run Code Online (Sandbox Code Playgroud)
我得到的只是一个约束,它的constraint_name条目是foo pkey指主键约束,而不是我对price列的检查。所以这个答案对我没有帮助,除非我遗漏了什么。
如何在不丢失任何数据的情况下删除此约束?
谢谢!
我在一张桌子上有 2 个触发器;一种适用于插入:
CREATE TRIGGER "get_user_name"
AFTER INSERT ON "field_data"
FOR EACH ROW EXECUTE PROCEDURE "add_info"();
Run Code Online (Sandbox Code Playgroud)
这会更新表中的一些值。
还有一个用于更新(填充历史表):
CREATE TRIGGER "set_history"
BEFORE UPDATE ON "field_data"
FOR EACH ROW EXECUTE PROCEDURE "gener_history"();
Run Code Online (Sandbox Code Playgroud)
问题是,当我在表中插入新行时,该过程"add_info"()会进行更新并因此触发第二个触发器,该触发器以错误结束:
Run Code Online (Sandbox Code Playgroud)ERROR: record "new" has no field "field1"
我怎样才能避免这种情况?
所以我有这个包含 620 万条记录的表,我必须对列执行具有相似性的搜索查询。查询可以是:
SELECT "lca_test".* FROM "lca_test"
WHERE (similarity(job_title, 'sales executive') > 0.6)
AND worksite_city = 'los angeles'
ORDER BY salary ASC LIMIT 50 OFFSET 0
Run Code Online (Sandbox Code Playgroud)
可以在 where(year = X, worksite_state = N, status = 'certified',visa_class = Z) 中添加更多条件。
运行其中一些查询可能需要很长时间,超过 30 秒。有时超过一分钟。
EXPLAIN ANALYZE 前面提到的查询给了我这个:
Run Code Online (Sandbox Code Playgroud)Limit (cost=0.43..42523.04 rows=50 width=254) (actual time=9070.268..33487.734 rows=2 loops=1) -> Index Scan using index_lca_test_on_salary on lca_test (cost=0.43..23922368.16 rows=28129 width=254) (actual time=9070.265..33487.727 rows=2 loops=1) >>>> Filter: (((worksite_city)::text = 'los angeles'::text) AND (similarity((job_title)::text, 'sales executive'::text) > 0.6::double precision)) …
postgresql index full-text-search pattern-matching postgresql-9.3
如果您能深入了解VACUUMPostgreSQL 9.3 中的功能,我将不胜感激。我通读了文档并进行了一些搜索,但找不到明确的答案。
我正在为 9.3 服务器设置每周一次的数据库维护工作。
其中一部分将是一个VACUUM FULL. 这是一个很小的数据库,我有一个不错的周末维护窗口,所以我可以FULL毫无问题地运行它。
ANALYZE在命令中添加选项有什么意义吗?
根据 9.3 文档:
VACUUM FULL将表的全部内容重写到一个没有额外空间的新磁盘文件中,允许将未使用的空间返回给操作系统。
如果表已完全重新创建,那么我是否需要特别要求ANALYZE发生或在将行写入表的新版本时自动更新统计信息?
我有一个 PostgreSQL 9.1 数据库,其中包含 10M+ 行和一些需要相似性和类似%word%搜索的文本字段,所以我决定使用 trigram 索引。
最初,我开始使用 GIN 索引,但现在我想知道我是否应该使用 GIST。
该理论说:
我试图同时创建GIN和GIST索引,并在实践中发现以下内容(在我的数据集上):
LIKE '%word%'查询,GIN 的速度与第一次 GIST 大致相同(甚至慢 5-20%)(当查询中的三元组索引尚未缓存时)。LIKE '%word%'查询,如果最近搜索了查询中的三元组,GIN 大约比 GIST 快5倍。无论缓存如何,GIST 始终具有相同的速度。% 'word'(相似性)查询,GIN 大约比 GIST慢5-8倍,具体取决于索引的缓存性。UPDATE表中有语句,它似乎增长得更快。除非,当然,我VACUUM FULL经常不够。所以我看到了理论和实践之间的一些差异:
在讨论这个问题的递归 CTE 解决方案时:
@ypercube偶然发现了一个令人惊讶的异常,这导致我们调查类型修饰符的处理。我们发现了令人惊讶的行为。
即使被指示不要这样做。最基本的例子:
SELECT 'vc8'::varchar(8)::varchar
Run Code Online (Sandbox Code Playgroud)
人们可能会期望varchar(没有修饰符),至少我会。但结果是varchar(8)(带修饰符)。下面的小提琴中有许多相关的案例。
不需要,所以这在相反的一面出错:
SELECT ARRAY['vc8']::varchar(8)[]
, ARRAY['vc8']::varchar(8)[] || 'vc8'::varchar(8)
Run Code Online (Sandbox Code Playgroud)
第一个表达式varchar(8)[]按预期产生。
但是第二个,在连接另一个之后varchar(8)被淡化到只是varchar[](没有修饰符)。来自array_append(),下面小提琴中的示例的类似行为。
在大多数情况下,所有这些都无关紧要。Postgres 不会丢失数据,并且当分配给列时,该值无论如何都会被强制转换为正确的类型。然而,相反方向的错误最终会导致一个令人惊讶的异常:
鉴于此简化表:
CREATE TABLE a (
vc8 varchar(8) -- with modifier
, vc varchar -- without
);
INSERT INTO a VALUES ('a', 'a'), ('bb', 'bb');
Run Code Online (Sandbox Code Playgroud)
虽然此 rCTE 对varchar列有效vc,但对 …
postgresql ×10
cte ×2
index ×2
alter-table ×1
cast ×1
concurrency ×1
datatypes ×1
debugging ×1
optimization ×1
performance ×1
plpgsql ×1
statistics ×1
trigger ×1
upsert ×1
vacuum ×1