PostgreSQL
 sql >> Teknologi Basis Data >  >> RDS >> PostgreSQL

Pemangkasan partisi berdasarkan batasan pemeriksaan tidak berfungsi seperti yang diharapkan

Kolom Anda created_at adalah timestamp without time zone .

Tapi now() mengembalikan timestamp with time zone . Ekspresi now() - '1 hour'::interval sedang dipaksa untuk timestamp [without time zone] , yang membawa dua masalah :

1.) Anda tidak meminta yang ini, tetapi ekspresinya tidak dapat diandalkan. Hasilnya tergantung pada pengaturan zona waktu saat ini dari sesi tempat kueri dieksekusi. Detailnya di sini:

Untuk memperjelas ekspresi, Anda dapat menggunakan:

now() AT TIME ZONE 'Europe/London' -- your time zone here

Atau cukup (baca manualnya di sini) :

LOCALTIMESTAMP  -- explicitly take the local time

Saya akan mempertimbangkan untuk bekerja dengan timestamptz sebagai gantinya.
Keduanya tidak menyelesaikan masalah kedua Anda:

2.) Jawab pertanyaan Anda. Pengecualian batasan tidak berfungsi. Per dokumentasi:

Penekanan saya yang berani.

now() adalah implementasi Postgres dari CURRENT_TIMESTAMP . Seperti yang Anda lihat di katalog sistem, hanya STABLE , bukan IMMUTABLE :

SELECT proname, provolatile FROM pg_proc WHERE proname = 'now';

proname | provolatile
--------+------------
now     | s              -- meaning: STABLE

Solusi

1.) Anda dapat mengatasi batasan dengan memberikan konstanta di WHERE kondisi (yang selalu "tidak berubah"):

select count(*) from events
where created_at > '2015-05-25 15:49:20.037815'::timestamp;  -- derived from your example

2.) Atau dengan "memalsukan" fungsi yang tidak dapat diubah:

CREATE FUNCTION f_now_immutable()
  RETURNS timestamp AS
$func$
SELECT now() AT TIME ZONE 'UTC'  -- your time zone here
$func$  LANGUAGE sql IMMUTABLE;

Dan kemudian:

select count(*) from events
where created_at > f_now_immutable() - interval '1 hour'

Hati-hati bagaimana Anda menggunakan ini:while now() adalah STABLE (tidak berubah selama durasi transaksi), tidak perubahan di antara transaksi, jadi berhati-hatilah untuk tidak menggunakannya dalam pernyataan yang disiapkan (kecuali sebagai nilai parameter) atau indeks atau apa pun yang dapat mengganggu Anda.

3.) Atau Anda dapat menambahkan konstanta yang tampaknya berlebihan WHERE klausa untuk kueri Anda saat ini yang cocok dengan batasan pada partisi Anda:

SELECT count(*)
FROM   events
WHERE  created_at > now() - '1 hour'::interval
AND    created_at >= '2015-04-01 00:00:00'::timestamp
AND    created_at <= '2015-04-30 23:59:59.999999'::timestamp;

Pastikan sendiri bahwa now() - '1 hour'::interval jatuh ke partisi yang tepat atau Anda tidak mendapatkan hasil, tentu saja.

Selain:Saya lebih suka menggunakan ekspresi ini di CHECK kendala dan permintaan. Lebih mudah untuk menangani dan melakukan hal yang sama:

       created_at >= '2015-04-01 0:0'::timestamp
AND    created_at <  '2015-05-01 0:0'::timestamp



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. ENUM ketik SQLAlchemy dengan PostgreSQL

  2. Postgres tidak menggunakan indeks pada array integer jika ekstensi intarray diinstal

  3. Ansible Loves PostgreSQL

  4. Cara menemukan tabel anak yang mewarisi dari tabel lain di PSQL

  5. Bagaimana cara melakukan pembaruan non-pemblokiran besar di PostgreSQL?