固定寬度的行會提高 PostgreSQL 的讀取性能嗎?
我有一張桌子
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)
我們在 Postgres 9.4.4 上。該機器在 SSD 上有 3.5 GB 記憶體和 150 GB 磁碟空間。
注意:應用程序始終將“published_date”四捨五入到最接近的日期。所有小時/分鐘/秒始終為 00。舊版。需要固定。等等。
此表有數億篇文章。該表接收來自(多達 16 個)並發程序的大量讀取查詢,這些程序執行以下查詢,我們的系統會盡快響應:
- 文章總數的計數
SELECT COUNT(*) FROM articles;
- 為給定使用者發布的所有文章的選擇
SELECT * FROM articles WHERE user_id = $1;
- 給定使用者最近發表的文章的選擇
SELECT * FROM articles WHERE user_id = $1 ORDER BY published_date DESC LIMIT 1;
我發現,在有大量工人的情況下,這些查詢非常慢。(在峰值負載下,第一個需要幾分鐘才能完成;另外兩個大約需要 10 秒。)特別是,查詢似乎正在排隊。
問題
*概括地說,只有固定寬度值的表是否比具有不同寬度值的表執行讀取查詢更好?(假裝磁碟空間不是問題。)*就我而言,我想知道如果我將“正文”文本欄位提取到單獨的表格並將字元可變欄位轉換為固定寬度,是否會看到性能改進字元欄位。
我承認這個問題有點貨物崇拜。我只是對 Postgres DB 引擎的內部了解不夠,無法建構一個有根據的假設。我確實打算用不同的模式和配置進行真正的實驗,但在我走得更遠之前,我想有一個關於 Postgres 實際工作方式的可靠心理模型。
相關問題
*我在哪裡可以了解有關 Postgres DB 引擎內部的更多資訊?*我用Google搜尋了上述問題的變體,但收效甚微。用於此搜尋的正確術語是什麼?這種級別的文件是否只存在於原始碼和 Postgres DBA 的頭腦中?我也謙虛地邀請有關該主題的好書的建議。
僅具有固定寬度值的表是否比具有不同寬度值的表執行讀取查詢更好?
**基本上沒有。**訪問列的成本非常低,但您無法衡量任何差異。細節:
特別是:
- 性能上完全沒有區別***。***您似乎認為(不像) 可能是“固定寬度”類型,但事實並非如此。兩者都是變長類型,只是增加了一個最大長度檢查:
character varying(255)``text
varchar(255)``text``varchar(255)
- 當所有值都是 36 個字元時,使用 char 與 varchar 進行索引查找會明顯更快嗎
在表定義中使用的
varchar(255)
通常表示對 Postgres 類型系統缺乏了解。它背後的架構師很可能不是母語人士 - 或者佈局已經從另一個 RDBMS(如 SQL Server)繼承而來,這在過去很重要。
- 您最昂貴的查詢甚至根本
SELECT COUNT(*) FROM articles
不考慮行數據,只有總大小間接重要。由於其 MVCC 模型,在 Postgres 中計算所有行的成本很高。也許估計足夠好,可以非常便宜地獲得?- 發現表行數的快速方法
(假裝磁碟空間不是問題。)
磁碟空間總是一個問題,即使你有足夠的空間。磁碟大小(必須讀取/處理/寫入的數據頁數)是影響性能的最重要因素之一。
我在哪裡可以了解有關 Postgres DB 引擎內部的更多資訊?
標籤postgres的資訊頁面具有指向更多資訊的最重要連結,包括書籍、Postgres Wiki 和優秀的手冊。後者是我個人的最愛。
您的第三個查詢有問題
SELECT * FROM articles WHERE user_id = $1 ORDER BY published_date DESC LIMIT 1;
ORDER BY published_date DESC
, 但published_date
可以為 NULL(無NOT NULL
約束)。如果可以有 NULL 值,那就是一個載入的腳槍,除非您更喜歡 NULL 值而不是最新的實際published_date
.要麼添加
NOT NULL
約束。始終對不能為 NULL 的列執行此操作。或者這樣做
ORDER BY published_date DESC
**NULLS LAST
**並相應地調整索引。"articles_user_id_published_date_idx" btree (user_id, published_date **DESC NULLS LAST**)
最近的相關答案中的詳細資訊:
轉換
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
較小的磁碟儲存確實會對性能產生影響。
更重要的是,您的索引
(user_id, published_date)
現在每個索引條目只佔用 32 個字節而不是 40 個字節,因為 2x4 字節不會產生額外的填充。這將對性能產生顯著影響。另外:此索引與展示的查詢無關。刪除除非索引,除非在別處使用:
"index_articles_on_published_date" btree (published_date)