我们的系统写入了大量数据(一种大数据系统)。写入性能足以满足我们的需求,但读取性能真的太慢了。
我们所有表的主键(约束)结构都相似:
timestamp(Timestamp) ; index(smallint) ; key(integer).
Run Code Online (Sandbox Code Playgroud)
一个表可以有数百万行,甚至数十亿行,而一个读请求通常是针对特定时间段(时间戳/索引)和标记的。查询返回大约 20 万行是很常见的。目前,我们每秒可以读取大约 15k 行,但我们需要快 10 倍。这是可能的,如果是,如何?
注意: PostgreSQL 是和我们的软件一起打包的,所以不同客户端的硬件是不一样的。
它是一个用于测试的虚拟机。VM 的主机是具有 24.0 GB RAM 的 Windows Server 2008 R2 x64。
Server 2008 R2 x64
2.00 GB of memory
Intel Xeon W3520 @ 2.67GHz (2 cores)
Run Code Online (Sandbox Code Playgroud)
postgresql.conf 优化shared_buffers = 512MB (default: 32MB)
effective_cache_size = 1024MB (default: 128MB)
checkpoint_segment = 32 (default: 3)
checkpoint_completion_target = 0.9 (default: 0.5)
default_statistics_target = 1000 (default: 100)
work_mem = 100MB (default: 1MB)
maintainance_work_mem = 256MB …Run Code Online (Sandbox Code Playgroud) 我在 PostgreSQL 9.0.8 中有一个很大的对象表(15M+ 行),我想查询过时的字段。
出于可扩展性和并发性的目的,我想将查询除以数百万,并且我想获取具有几天前日期的 updated_at 字段的所有数据。
我已经在 100 万个 ID 上尝试了许多索引和查询,但使用 Heroku 的 Ronin 硬件似乎无法在 100 秒内获得性能。
我正在寻找我尚未尝试使其尽可能高效的建议。
尝试 #1
EXPLAIN ANALYZE SELECT count(*) FROM objects
WHERE (date(updated_at)) < (date(now())-7) AND id >= 5000001 AND id < 6000001;
INDEX USED: (date(updated_at),id)
268578.934 ms
Run Code Online (Sandbox Code Playgroud)
尝试 #2
EXPLAIN ANALYZE SELECT count(*) FROM objects
WHERE ((date(now()) - (date(updated_at)) > 7)) AND id >= 5000001 AND id < 6000001;
INDEX USED: primary key
335555.144 ms
Run Code Online (Sandbox Code Playgroud)
尝试 #3
EXPLAIN ANALYZE SELECT count(*) FROM …Run Code Online (Sandbox Code Playgroud) postgresql performance index partitioning postgresql-performance
问这个问题,特别是针对 Postgres,因为它对 R 树/空间索引有很好的支持。
我们有下表,其中包含单词及其频率的树结构(嵌套集模型):
lexikon
-------
_id integer PRIMARY KEY
word text
frequency integer
lset integer UNIQUE KEY
rset integer UNIQUE KEY
Run Code Online (Sandbox Code Playgroud)
和查询:
SELECT word
FROM lexikon
WHERE lset BETWEEN @Low AND @High
ORDER BY frequency DESC
LIMIT @N
Run Code Online (Sandbox Code Playgroud)
我认为覆盖索引(lset, frequency, word)会很有用,但我觉得如果范围内的lset值太多,它可能表现不佳(@High, @Low)。
(frequency DESC)有时,当使用该索引的搜索早期产生@N与范围条件匹配的行时,一个简单的索引也可能就足够了。
但似乎性能在很大程度上取决于参数值。
有没有办法让它快速执行,不管范围(@Low, @High)是宽还是窄,也不管高频词是否幸运地在(窄)选择的范围内?
R-tree/空间索引有帮助吗?
添加索引,重写查询,重新设计表,没有限制。
postgresql performance index database-design query-performance
我最近一直在学习bit string数据类型,我很好奇:
在这个文档页面的底部有一句话:
...加上 5 或 8 个字节的开销,具体取决于字符串的长度
在其他语言(如 PHP、Java、C#、C++ 等)中,如何通过 Npgsql、ODBC 等驱动程序处理位字符串?
对于问题 #1,使用 smallint 或 bigint 将提高存储效率,并且可能会提供性能提升,因为在任何地方都支持整数。大多数编程语言都可以轻松处理整数的位操作。如果是这样,那么引入位串数据类型的意义何在?是否仅适用于需要大量位掩码的情况?位域索引可能吗?我对 PostgreSQL 中如何进行位域索引比较好奇。
对于#2,我很困惑,不仅仅是好奇。例如,如果我将工作日位掩码存储在 bit(7) 字段中,一天一位,最低位代表星期一。然后我在 PHP 和 C++ 中查询该值。我会得到什么?文档说我会有一个位串,但是位串不是我可以直接使用的 - 就像整数一样。那么在这种情况下,我应该放弃位域吗?
任何人都可以详细说明为什么以及何时应该使用一点或一点变化?
我有一张这样的表:
CREATE TABLE products (
id serial PRIMARY KEY,
category_ids integer[],
published boolean NOT NULL,
score integer NOT NULL,
title varchar NOT NULL);
Run Code Online (Sandbox Code Playgroud)
一个产品可以属于多个类别。category_ids列包含所有产品类别的 id 列表。
典型的查询看起来像这样(总是搜索单个类别):
SELECT * FROM products WHERE published
AND category_ids @> ARRAY[23465]
ORDER BY score DESC, title
LIMIT 20 OFFSET 8000;
Run Code Online (Sandbox Code Playgroud)
为了加快速度,我使用以下索引:
CREATE INDEX idx_test1 ON products
USING GIN (category_ids gin__int_ops) WHERE published;
Run Code Online (Sandbox Code Playgroud)
除非某一类别中的产品太多,否则这会很有帮助。它会快速过滤掉属于该类别的产品,但随后必须以艰难的方式完成排序操作(没有索引)。
已安装的btree_gin扩展允许我像这样构建多列 GIN 索引:
CREATE INDEX idx_test2 ON products USING GIN (
category_ids gin__int_ops, score, title) WHERE published; …Run Code Online (Sandbox Code Playgroud) 无法O (log n)及时索引和执行查询。
该查询包括一个INNER JOIN、一个ORDER BY和一个相等运算。如果我正确理解了数据库的规律,O (log n)如果一个非等式运算符没有在多于一列上使用,则可以及时(或大约)索引和执行查询。在这种情况下,我相信INNER JOIN确实算作相等运算符,而非相等运算符将是ORDER BY查询的一部分。该表有超过 10,000,000 行,需要每秒处理多次读取和写入。
使用 PostgreSQL。这就是桌子的样子。如您所见,“Names”列是一个列表属性,它是与之相反的列INNER JOIN:
Age Names Date
34 ['carla', 'john', 'sam'] 3/13/2011
26 ['json', 'cindy', 'joel'] 3/13/2011
72 ['beth', 'amber', 'susie'] 3/13/2011
14 ['john', 'jim', 'debie'] 3/13/2011
Run Code Online (Sandbox Code Playgroud)
这是我们尝试执行的查询:
SELECT * FROM the_table WHERE Age==26 AND Names=='john' ORDER BY Date
Run Code Online (Sandbox Code Playgroud)
我的背景来自使用 App Engine 的 Big Table,所以我在这里使用了相等运算符来指示它'john'应该是Names列中的名称之一。这将是 GAE 大表中可接受的查询,它将O (log N)及时执行,因为所有大表查询都需要执行。我假设在 …