PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

Как да накарам заявката date_part да достигне индекс?

Е, и двете ви заявки са на различни таблици (reportimpression спрямо reportimpressionday ), така че сравнението на двете заявки наистина не е сравнение. АНАЛИЗИРАХТЕ ли? и двете? Различни статистически данни за колони също могат да играят роля. Раздуването на индекса или таблицата може да е различно. По-голяма част от всички редове отговарят ли на изискванията за февруари 2019 г.? И т.н.

Един изстрел в тъмното, сравнете процентите за двете таблици:

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;

Това е за reportimpression по-голям? Тогава може просто да надхвърли броя, за който се очаква индексът да помогне.

Обикновено вашият индекс reportimpression_datelocal_index на (местна дата) изглежда добре за него и reportimpression_viewership_index дори позволява сканиране само за индекс, ако autovacuum победи натоварването на запис върху масата. (Въпреки че импресии &възрастова група са просто мъртъв товар за това и ще работи дори по-добре без).

Отговор

Имате 26,6 процента, а денят е 26,4 процента за моето запитване. За такъв голям процент индексите обикновено изобщо не са полезни . Последователното сканиране обикновено е най-бързият начин. Само сканиране само с индекс може все пак има смисъл, ако основната таблица е много по-голяма. (Или имате тежка раздуване на таблицата и по-малко раздути индекси, което прави индексите отново по-привлекателни.)

Първото ви запитване може просто да е през повратната точка. Опитайте да стесните времевата рамка, докато видите сканирания само за индекс. Няма да видите (растерно) сканиране на индекс с повече от приблизително 5% от всички редове, отговарящи на условията (зависи от много фактори).

Заявки

Както и да е, разгледайте тези модифицирани заявки:

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;

Основни точки

  • Когато използвате локализиран формат за дата като '2-1-2019' , преминете през to_timestamp() с изрични спецификатори на формат. В противен случай това зависи от локалните настройки и може да прекъсне (тихо) при извикване от сесия с различни настройки. По-скоро използвайте ISO формати за дата/час, както е показано, които не зависят от локалните настройки.

  • Изглежда, че искате да включите целия месец от февруари. Но вашата заявка пропуска горната граница. От една страна, февруари може да има 29 дни. локална дата <'2-28-2019' изключва и всички 28 фев. Използвайте datelocal <'2019-03-01' вместо това.

  • По-евтино е да групирате и сортирате по един и същи израз както имате в SELECT изброй, ако можеш. Затова използвайте date_trunc() там също. Не използвайте различни изрази без нужда. Ако имате нужда частта от датата в резултата, приложете я върху групирания израз, като:

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

    Малко по-шумен код, но по-бърз (и вероятно по-лесен за оптимизиране и за планиране на заявки).

  • Използвайте обединения ФИЛТЪР клаузата в Postgres 9.4 или по-нова версия. По-чист е и малко по-бърз. Вижте:




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Как да създадете групи с равни размери

  2. Подобряване на скоростта на заявка:прост SELECT в голяма таблица Postgres

  3. Мигриране на PostgreSQL text/bytea колона към голям обект?

  4. Атрибут номер 10 надвишава броя на колоните 0

  5. Как страната FROM на UPDATE се отнася към таблицата, насочена към UPDATE?