Postgresql

將日期時間拆分為餐廳預訂模式的 2 列?

  • November 27, 2020

使用 PostgreSQL。

其主要驅動因素是,雖然沒有日期和時間就不會存在預訂,但使用者可以使用時間或日期或兩者來搜尋和監控預訂。使用單個列,我將不斷地不得不將其分解並通過搜尋date_trunc

雖然 PostgreSQL 允許基於函式創建索引,但explain表明這並未用於使用date_trunc.

桌子:

development2=# \d reservations
                                       Table "public.reservations"
    Column      |            Type             |                         Modifiers                         
-----------------+-----------------------------+-----------------------------------------------------------
id              | integer                     | not null default nextval('reservations_id_seq'::regclass)
tops            | integer                     | not null
price           | numeric                     | 
state           | integer                     | not null
restaurant_id   | integer                     | not null
seller_id       | integer                     | 
customer_id     | integer                     | 
created_at      | timestamp without time zone | not null
start           | timestamp without time zone | 
Indexes:
   "reservations_pkey" PRIMARY KEY, btree (id)
   "start_date_index" btree (date_trunc('day'::text, start))
Foreign-key constraints:
   "reservations_customer_id_fk" FOREIGN KEY (customer_id) REFERENCES users(id)
   "reservations_restaurant_id_fk" FOREIGN KEY (restaurant_id) REFERENCES restaurants(id)
   "reservations_seller_id_fk" FOREIGN KEY (seller_id) REFERENCES users(id)

詢問:

development2=# explain select id,start from reservations where date_trunc('day', start) = '2014-03-14';
                                          QUERY PLAN                                            
-------------------------------------------------------------------------------------------------
Seq Scan on reservations  (cost=0.00..1.01 rows=1 width=12)
  Filter: (date_trunc('day'::text, start) = '2014-03-14 00:00:00'::timestamp without time zone)
(2 rows

)

甚至不知道如何進行時間搜尋,to_char+IMMUTABLE我猜……

timestampdatetime

如果您對時間戳的日期部分感興趣,則直接轉換它會更便宜。結果是一個實際的date,而date_trunc()返回一個timestamp!(您可以date依次將其轉換為,但不要打擾。)您的索引應該是:

CREATE INDEX start_date_index ON reservations (cast(start AS date));

cast(column AS type)在索引定義中使用更詳細的標準表示法。在這種情況下,Postgres 速記將需要一組額外的括號:(column::type). 您仍然可以在查詢中使用任何一種表示法來匹配:

SELECT id, start
FROM   reservations
WHERE  start::date = '2014-03-14';

看:

start::time如果需要,您可以做類似的事情。

無論哪種方式,我當然不會拆分日期和時間部分。時間戳幾乎總是出眾的設計。

索引調整

根據您的實際案例,您可以將其設為多列索引,包括id

CREATE INDEX start_id_date_index ON reservations (cast(start AS date), id);

這將完美地服務於上述查詢,甚至可能使用僅索引掃描。而且由於您現在date在索引中使用實際值(4 個字節),因此額外的整數列(也是 4 個字節)非常適合性能。看:

更重要的是,您還可以在timestamp列上使用普通索引:

CREATE INDEX start_start_index ON reservations (start);

只要確保你的WHERE條件是“sargable”。喜歡:

SELECT id, start
FROM   reservations
WHERE  start >= '2014-03-14 0:0'::timestamp
WHERE  start <  '2014-03-15 0:0'::timestamp;

這將使用索引。

最佳解決方案取決於您所有要求的總和。此外,儘管如此,Postgres 仍可以使用您原來的、不太理想的索引。你的表中有多少行?只有少數,順序掃描總是更快,您不會看到索引掃描。

引用自:https://dba.stackexchange.com/questions/60905