Eh bien, vos deux requêtes sont sur des tables différentes (reportimpression
vs reportimpressionday
), donc la comparaison des deux requêtes n'est vraiment pas une comparaison. Avez-vous ANALYZE
tous les deux? Diverses statistiques de colonne peuvent également jouer un rôle. Le gonflement de l'index ou de la table peut être différent. Une plus grande partie de toutes les rangées est-elle éligible pour février 2019 ? Etc.
Un coup dans le noir, comparez les pourcentages des deux tableaux :
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;
Est-ce celui pour reportimpression
plus gros? Ensuite, il pourrait simplement dépasser le nombre pour lequel un index est censé aider.
Généralement, votre index reportimpression_datelocal_index
le (datelocal) semble bon pour cela, et reportimpression_viewership_index
autorise même les analyses d'index uniquement si autovacuum dépasse la charge d'écriture sur la table. (Bien que les impressions
&agegroup
sont juste des marchandises mortes pour cela et cela fonctionnerait encore mieux sans).
Répondre
Vous avez 26.6 percent, and day is 26.4 percent
pour ma requête. Pour un pourcentage aussi élevé, les index ne sont généralement pas utiles du tout . Une analyse séquentielle est généralement le moyen le plus rapide. Seules les analyses d'index uniquement peuvent ont toujours un sens si la table sous-jacente est beaucoup plus grande. (Ou vous avez grave gonflement des tables et des index moins gonflés, ce qui rend les index à nouveau plus attrayants.)
Votre première requête peut être juste à travers le point de basculement. Essayez de réduire la période jusqu'à ce que vous voyiez des analyses d'index uniquement. Vous ne verrez pas d'analyses d'index (bitmap) avec plus d'environ 5 % de toutes les lignes qualifiées (cela dépend de nombreux facteurs).
Requêtes
Quoi qu'il en soit, considérez ces requêtes modifiées :
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;
Points majeurs
-
Lors de l'utilisation du format de date localisé comme
'2-1-2019'
, passez parto_timestamp()
avec des spécificateurs de format explicites. Sinon, cela dépend des paramètres régionaux et peut se briser (silencieusement) lorsqu'il est appelé à partir d'une session avec des paramètres différents. Utilisez plutôt les formats de date/heure ISO comme démontré qui ne dépendent pas des paramètres régionaux. -
Il semble que vous souhaitiez inclure le mois entier de février. Mais votre requête manque la limite supérieure. D'une part, février peut avoir 29 jours. Un
datelocal < '2-28-2019'
exclut également tout le 28 février. Utilisezdatelocal < '2019-03-01'
à la place. -
Il est moins cher de regrouper et trier par la même expression comme vous l'avez dans le
SELECT
liste si vous le pouvez. Utilisez doncdate_trunc()
ici aussi. N'utilisez pas d'expressions différentes sans nécessité. Si vous avez besoin la partie de date dans le résultat, appliquez-la sur l'expression groupée, comme :SELECT date_part('day', date_trunc('day', datelocal)) AS day ... GROUP BY date_trunc('day', datelocal) ORDER BY date_trunc('day', datelocal);
Code un peu plus bruyant, mais plus rapide (et peut-être plus facile à optimiser également pour le planificateur de requêtes).
-
Utilisez le agrégat
FILTER
clause dans Postgres 9.4 ou ultérieur. C'est plus propre et un peu plus rapide. Voir :