Vous n'êtes pas identifié(e).
Pages : 1
Bonjour,
Je me tire un peu les cheveux après avoir lu :
https://paquier.xyz/postgresql-2/postgr … heap-scan/
https://www.postgresql.org/message-id/0 … .ntt.co.jp
En substance, il serait question d'avoir un indice du work_mem qu'il faudrait par rapport à une requête présentant des "lossy bitmaps".
La formule donnée est :
work_mem (bytes) = (Number of lossy pages + number of exact pages) *
(MAXALIGN(sizeof(HASHELEMENT)) + MAXALIGN(sizeof(PagetableEntry))
+ sizeof(Pointer) + sizeof(Pointer))
J'ai une requête présentant des lossy bitmaps mais je n'arrive déjà pas à retrouver la valeur de 3.2 MB donnée dans l'exemple !
En supposant que :
Number of lossy pages + number of exact pages = 39709 (Heap Blocks: exact=338 lossy=39371)
MAXALIGN(sizeof(HASHELEMENT)) = 8 car MAXALIGN sur un 64-bit est à 8, et que le HASHELEMENT ici est un int4 à 4
sizeof(Pointer) = 4
j'en arrive à :
3.2 MB = 39709 * ( 16 + MAXALIGN(sizeof(PagetableEntry)) )
mais dire que MAXALIGN(sizeof(PagetableEntry)) = 84 ... je n'arrive pas à l'expliquer (je commençais à calculer le Page Header de 23+1 bytes ... )
Merci d'éclairer ma lanterne.
Ludovic
Hors ligne
Vous voulez dire 84 - 16?
Mais j'imagine que Michael avait un pc 64 bits, et donc sizeof(Pointer) == 8 et non 4, et de plus :
typedef struct HASHELEMENT
{
struct HASHELEMENT *link; /* link to next entry in same bucket */
uint32 hashvalue; /* hash function result for this entry */
} HASHELEMENT;
(gdb) p sizeof(HASHELEMENT )
$1 = 16
Julien.
https://rjuju.github.io/
Hors ligne
Merci pour ce rapide retour.
Oui pardon je voulais dire 84-16 évidemment.
Effectivement, je partais mal avec mon sizeof(HASHELEMENT) (je pensais que c'était la place du type de la colonne de la table, la colonne sur laquelle se faisait le Hash ...)
Et pour le sizeof(Pointer), je n'avais dû tomber que sur des exemples 32-bit ...
Bref, je repars avec :
MAXALIGN(sizeof(HASHELEMENT)) = 16
sizeof(Pointer) = 8
Et j'arrive à :
3.2 MB = 39709 * ( MAXALIGN(sizeof(HASHELEMENT)) + MAXALIGN(sizeof(PagetableEntry)) + sizeof(Pointer) + sizeof(Pointer))
3.2 MB = 39709 * ( 16 + MAXALIGN(sizeof(PagetableEntry)) + 8 + 8)
Donc MAXALIGN(sizeof(PagetableEntry)) = 52,5008 ? disons 52 (et cela se tient : 39709*(32+52) = 39709*84 = 3335556 == 3,181034088 MB)
mais 52 ce n'est pas un multiple de 8 ... (et 48 et 56 sont trop loin)
le MAXALIGN serait bien un multiple de 8 sur un 64-bit ?
J'ai lu/relu aussi cette page : https://stackoverflow.com/questions/135 … -row-sizes
et j'ai envie de croire que je peux calculer la taille ainsi :
23 -- heaptupleheader
+ 1 -- padding or NULL bitmap
+ 4 -- 1 * integer (no alignment padding here)
+ 4 -- padding (pour arriver à un multiple de 8)
= 32
+ 0 -- no padding since tuple ends at multiple of MAXALIGN
mais je dois m'égarer car je ne suis pas à 52.
La seule chose que je remarque c'est que 52 ressemble à l'exemple : 48 (un multiple de 8) + un item pointer à 4 bytes (mais on a dit que sizeof(Pointer) == 8 )
Bref, je cale encore.
Dernière modification par LudovicG (09/03/2020 15:57:12)
Ludovic
Hors ligne
sizeof(PagetableEntry) == 48 == MAXALIGN(sizeof(PagetableEntry))
Le calcul donne 3176720, ce qui est "approximately 3.2MB of work_mem", sachant qu'il faut bien évidemment arrondir au supérieur plutôt qu'à l'inférieur. À mon avis il ne faut pas chercher plus loin.
Julien.
https://rjuju.github.io/
Hors ligne
Hum ok
Du coup, afin de pouvoir poursuivre sur mon cas perso, qu'est-ce que "PagetableEntry" ?
Si c'est une valeur fixe à 48 qu'il ne faut pas chercher à comprendre ok (mais sinon ...)
Ludovic
Hors ligne
Il s'agit de la structure utilisée par les bitmap pour stocker le coeur de l'information: soit la liste des lignes dans le cas d'une page bitmap "exact", soit une liste de blocs dans le cas contraire:
/*
* The hashtable entries are represented by this data structure. For
* an exact page, blockno is the page number and bit k of the bitmap
* represents tuple offset k+1. For a lossy chunk, blockno is the first
* page in the chunk (this must be a multiple of PAGES_PER_CHUNK) and
* bit k represents page blockno+k. Note that it is not possible to
* have exact storage for the first page of a chunk if we are using
* lossy storage for any page in the chunk's range, since the same
* hashtable entry has to serve both purposes.
*
* recheck is used only on exact pages --- it indicates that although
* only the stated tuples need be checked, the full index qual condition
* must be checked for each (ie, these are candidate matches).
*/
typedef struct PagetableEntry
{
BlockNumber blockno; /* page number (hashtable key) */
char status; /* hash entry status */
bool ischunk; /* T = lossy storage, F = exact */
bool recheck; /* should the tuples be rechecked? */
bitmapword words[Max(WORDS_PER_PAGE, WORDS_PER_CHUNK)];
} PagetableEntry;
Cela se trouve dans le fichier src/backend/nodes/tidbitmap.c.
Julien.
https://rjuju.github.io/
Hors ligne
Ok, merci pour tout !
Ma lanterne vient de s'éclairer !
Ludovic
Hors ligne
Pages : 1