bob*_*opy 9 postgresql performance datatypes postgresql-9.4 query-performance
我有一张桌子articles:
Table "articles"
Column | Type | Modifiers | Storage | Stats target | Description
----------------+-----------------------------+----------------------------------------------------+----------+--------------+-------------
id | integer | not null default nextval('articles_id_seq'::regclass) | plain | |
user_id | integer | | plain | |
title | character varying(255) | | extended | |
author | character varying(255) | | extended | |
body | text | default '--- [] +| extended | |
| | '::text | | |
created_at | timestamp without time zone | | plain | |
updated_at | timestamp without time zone | | plain | |
published_date | timestamp without time zone | | plain | |
Indexes:
"articles_pkey" PRIMARY KEY, btree (id)
"index_articles_on_published_date" btree (published_date)
"index_rents_on_user_id" btree (user_id)
"index_articles_on_user_id_and_published_date" btree (user_id, published_date)
Run Code Online (Sandbox Code Playgroud)
我们在 Postgres 9.4.4 上。该机器在 SSD 上具有 3.5 GB 内存和 150 GB 磁盘空间。
注意:“published_date”总是由应用程序四舍五入到最接近的日期。所有小时/分钟/秒始终为 00。传统。需要固定。等等。
这个表有数亿篇文章。该表从(多达 16 个)并发进程接收大量读取查询,以我们的系统响应的速度执行以下查询:
文章总数的计数
SELECT COUNT(*) FROM articles;
Run Code Online (Sandbox Code Playgroud)
为给定用户发布的所有文章的选择
SELECT * FROM articles WHERE user_id = $1;
Run Code Online (Sandbox Code Playgroud)
为给定用户选择最近发表的文章
SELECT * FROM articles WHERE user_id = $1 ORDER BY published_date DESC LIMIT 1;
Run Code Online (Sandbox Code Playgroud)
我发现,由于有大量工作人员,这些查询非常缓慢。(在峰值负载时,第一个需要几分钟才能完成;另外两个大约需要 10 秒。)特别是,查询似乎正在排队。
抽象地说,只有固定宽度值的表是否比具有不同宽度值的表执行读取查询更好?(假装磁盘空间不是问题。)在我的情况下,我想知道如果我将“正文”文本字段提取到单独的表并将字符变化字段转换为固定宽度,我是否会看到性能改进字符字段。
我承认这个问题有点货物崇拜。我只是对 Postgres DB 引擎的内部结构知之甚少,无法构建有根据的假设。我确实打算用不同的模式和配置进行真实的实验,但在我进一步研究之前,我想对 Postgres 的实际工作方式有一个可靠的心理模型。
在哪里可以了解有关 Postgres 数据库引擎内部结构的更多信息?我在谷歌上搜索了上述问题的变体,但收效甚微。用于此搜索的正确术语是什么?这种级别的文档是否只存在于源代码和 Postgres DBA 的脑海中?我也虚心邀请有关该主题的好书的建议。
Erw*_*ter 13
仅具有固定宽度值的表是否比具有不同宽度值的表执行读取查询更好?
基本上没有。访问列时的成本非常低,但您将无法衡量任何差异。细节:
特别是:
character varying(255),并text 在所有。您似乎认为varchar(255)(与 不同text)可能是“固定宽度”类型,但事实并非如此。两者都是变长类型,varchar(255)只是增加了一个最大长度检查:varchar(255)在表定义中使用 ,通常表明缺乏对 Postgres 类型系统的理解。它背后的架构师很可能不是母语人士 - 或者布局已经从另一个 RDBMS(如 SQL Server)继承而来,这曾经很重要。
SELECT COUNT(*) FROM articles,即使不考虑行数据在所有的,只是总大小间接事项。由于其 MVCC 模型,在 Postgres 中计算所有行的成本很高。也许估计就足够了,可以非常便宜地获得?(假装磁盘空间不是问题。)
磁盘空间始终是一个问题,即使您有足够的空间。磁盘大小(必须读取/处理/写入的数据页数)是影响性能的最重要因素之一。
在哪里可以了解有关 Postgres 数据库引擎内部结构的更多信息?
标签postgres的信息页面具有指向更多信息的最重要链接,包括书籍、Postgres Wiki 和优秀手册。后者是我个人的最爱。
SELECT * FROM articles WHERE user_id = $1 ORDER BY published_date DESC LIMIT 1;
Run Code Online (Sandbox Code Playgroud)
ORDER BY published_date DESC,但published_date可以为 NULL(无NOT NULL约束)。如果可以有 NULL 值,那是一个满载的脚步,除非您更喜欢 NULL 值而不是最新的实际published_date.
要么添加NOT NULL约束。始终对不能为 NULL 的列执行此操作。
或者做那个ORDER BY published_date DESCNULLS LAST并相应地调整索引。
"articles_user_id_published_date_idx" btree (user_id, published_date DESC NULLS LAST)Run Code Online (Sandbox Code Playgroud)
最近的相关答案中的详细信息:
published_date为实际date虽然'published_date' is always rounded,它实际上只是一个date占用 4 个字节而不是 8 个字节的timestamp. 您最好在表定义中将其向上移动到两timestamp列之前,这样您就不会丢失 4 个字节来填充:
...
body | text
published_date | date -- <---- here
created_at | timestamp without time zone
updated_at | timestamp without time zone
Run Code Online (Sandbox Code Playgroud)
较小的磁盘存储确实会对性能产生影响。
更重要的是,您的索引(user_id, published_date)现在每个索引条目只占用 32 个字节而不是 40 个,因为 2x4 字节不会产生额外的填充。这将对性能产生显着影响。
旁白:此索引与演示的查询无关。删除除非索引,除非在其他地方使用:
"index_articles_on_published_date" btree (published_date)
| 归档时间: |
|
| 查看次数: |
1694 次 |
| 最近记录: |