J'essaie de diffuser des données binaires dans un champ bytea
. Le processus est assez simple:
loop until the end of the incoming stream
UPDATE myTable SET data = data || $chunk WHERE id = myId
$chunk
Est une liaison pour le flux de courant actuelmyId
) existe déjà avec des données NULLTout fonctionne correctement s'attendre à ce que les données de concaténation deviennent de plus en plus lentes car les morceaux sont stockés.
Depuis que j'ai besoin de garder mon SQL assez portable, je ne peux pas utiliser "objets de grande grasse postgresql"
Est-il possible d'optimiser ce processus?
overlay()
pour placer chaque morceau?Mise à jour d'une ligne dans un modèle multiversion Comme Postgres signifie créer une deuxième copie de cette ligne avec le nouveau contenu. Physiquement, il n'y a pas de mise à jour sur place: la mise à jour est similaire à Supprimer + Insérer le nouveau contenu.
Donc, dans la boucle ci-dessus, le premier morceau, au lieu d'être écrit une fois, est écrit N fois, le deuxième morceau est écrit N-1 fois, le troisième N-2 fois et ainsi de suite.
Pour que cela aggrave, toutes ces écrivies doivent également aller dans les fichiers WAL pour la journalisation et toutes les versions intermédiaires des lignes devront être ramassées par le processus d'autovachage pour être éventuellement mis au rebut.
En supposant que ces morceaux ne puissent être assemblés sur le client et doivent être diffusés, cela pourrait aider à faire quelque chose comme ceci:
CREATE TEMPORARY sequence s;
CREATE TEMPORARY TABLE buffer(seq int default nextval('s'), chunk bytea);
-- buffer in temporary storage
LOOP
INSERT INTO buffer(chunk) VALUES ($chunk)
END LOOP
-- assemble in final storage
INSERT INTO permanent_table(data)
SELECT string_agg(chunk,''::bytea order by seq) FROM buffer;
TRUNCATE (or DROP) TABLE buffer;
Au moins, les morceaux ne seront écrits que deux fois (une fois dans le stockage tampon et une fois en stockage durable final), et une seule fois dans le journal, comme la table temporaire ne sera pas connectée à Wal.