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

Bagaimana cara mendapatkan kueri date_part untuk mencapai indeks?

Nah, kedua kueri Anda berada di tabel yang berbeda (reportimpression vs. reportimpressionday ), jadi perbandingan dua kueri sebenarnya bukan perbandingan. Apakah Anda ANALYZE keduanya? Berbagai statistik kolom juga dapat berperan. Indeks atau tabel mengasapi mungkin berbeda. Apakah sebagian besar dari semua baris memenuhi syarat untuk Februari 2019? dll.

Satu bidikan dalam gelap, bandingkan persentase untuk kedua tabel:

SELECT tbl, round(share * 100 / total, 2) As percentage
FROM  (
   SELECT text 'reportimpression' AS tbl
        , count(*)::numeric AS total
        , count(*) FILTER (WHERE datelocal >= '2019-02-01' AND datelocal < '2019-03-01')::numeric AS share
   FROM  reportimpression

   UNION ALL
   SELECT 'reportimpressionday'
        , count(*)
        , count(*) FILTER (WHERE datelocal >= '2019-02-01' AND datelocal < '2019-03-01')
   FROM  reportimpressionday
  ) sub;

Apakah yang untuk reportimpression lebih besar? Maka mungkin saja melebihi jumlah yang diharapkan dapat membantu indeks.

Secara umum, reportimpression_datelocal_index indeks Anda pada (datelocal) terlihat bagus untuk itu, dan reportimpression_viewership_index bahkan memungkinkan pemindaian hanya indeks jika autovacuum mengalahkan beban tulis di atas meja. (Meskipun impressions &agegroup hanya pengiriman mati untuk ini dan itu akan bekerja lebih baik tanpa).

Jawab

Anda mendapatkan 26.6 percent, and day is 26.4 percent untuk pertanyaan saya. Untuk persentase sebesar itu, indeks biasanya tidak berguna sama sekali . Pemindaian berurutan biasanya merupakan cara tercepat. Hanya pemindaian indeks saja yang dapat masih masuk akal jika tabel yang mendasarinya jauh lebih besar. (Atau Anda memiliki parah tabel bloat, dan indeks yang lebih sedikit, yang membuat indeks lebih menarik lagi.)

Permintaan pertama Anda mungkin berada di titik kritis. Coba persempit kerangka waktu hingga Anda melihat pemindaian hanya indeks. Anda tidak akan melihat pemindaian indeks (bitmap) dengan lebih dari 5% dari semua baris yang memenuhi syarat (tergantung pada banyak faktor).

Permintaan

Bagaimanapun, pertimbangkan kueri yang dimodifikasi ini:

SELECT date_part('hour', datelocal)                AS hour
     , SUM(views) FILTER (WHERE gender = 'male')   AS male
     , SUM(views) FILTER (WHERE gender = 'female') AS female
FROM   reportimpression
WHERE  datelocal >= '2019-02-01'
AND    datelocal <  '2019-03-01' -- '2019-02-28'  -- ?
GROUP  BY 1
ORDER  BY 1;

SELECT date_trunc('day', datelocal)                AS day
     , SUM(views) FILTER (WHERE gender = 'male')   AS male
     , SUM(views) FILTER (WHERE gender = 'female') AS female
FROM   reportimpressionday
WHERE  datelocal >= '2019-02-01'
AND    datelocal <  '2019-03-01'
GROUP  BY 1
ORDER  BY 1;

Poin utama

  • Saat menggunakan format tanggal yang dilokalkan seperti '2-1-2019' , buka to_timestamp() dengan penentu format eksplisit. Kalau tidak, ini tergantung pada pengaturan lokal dan mungkin rusak (diam-diam) ketika dipanggil dari sesi dengan pengaturan yang berbeda. Sebaiknya gunakan format tanggal/waktu ISO seperti yang ditunjukkan yang tidak bergantung pada pengaturan lokal.

  • Sepertinya Anda ingin menyertakan seluruh bulan dari Februari. Tetapi kueri Anda meleset dari batas atas. Untuk satu, Februari mungkin memiliki 29 hari. Sebuah datelocal < '2-28-2019' tidak termasuk semua 28 Februari juga. Gunakan datelocal < '2019-03-01' sebagai gantinya.

  • Lebih murah untuk mengelompokkan &mengurutkan menurut ekspresi yang sama seperti yang Anda miliki di SELECT daftar jika Anda bisa. Jadi gunakan date_trunc() di sana juga. Jangan gunakan ekspresi yang berbeda tanpa perlu. Jika Anda membutuhkan bagian tanggal dalam hasil, terapkan pada ekspresi yang dikelompokkan, seperti:

    SELECT date_part('day', date_trunc('day', datelocal)) AS day
    ...
    GROUP  BY date_trunc('day', datelocal)
    ORDER  BY date_trunc('day', datelocal);
    

    Kode sedikit lebih berisik, tetapi lebih cepat (dan mungkin lebih mudah untuk dioptimalkan untuk perencana kueri juga).

  • Gunakan agregat FILTER klausa di Postgres 9.4 atau lebih baru. Ini lebih bersih dan sedikit lebih cepat. Lihat:




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Ubah byte menjadi presisi ganda di PostgreSQL

  2. Menghubungkan Excel ke PostgreSQL melalui VBA

  3. Jumlahkan sampai nilai ambang tercapai dan kemudian setel ulang penghitung

  4. Kunci utama komposit PostgreSQL

  5. Fungsi PostgreSQL age():hasil yang berbeda/tidak terduga saat mendarat di bulan yang berbeda