Vous n'êtes pas identifié(e).
Pages : 1
Bonjour à tous,
Je vous fait part de mon souci, je suis dessus depuis un bon petit moment et je ne comprends pas du tout d'où peut venir l'erreur ...
J'ai un champ crypté, avec comme donnée en claire : "mamané"
J'arrive bien à le récupérer :
convert_from(decrypt(name::bytea, 'salt', 'bf'), 'UTF-8') => "mamané"
On est bon sur ça !
Maintenant je crypte cette valeur :
encode(public.digest('mamané', 'sha1'), 'hex') => "2bfb316cf461d1a884e0b24c4d90de0bfe25f04f"
Mais là est tout le souci ... Si je fais la même chose mais sur le champ name (comme au dessus), je n'obtiens pas le même hash ...
encode(public.digest(convert_from(decrypt(name::bytea, 'salt', 'bf'), 'UTF-8'), 'sha1'), 'hex') => "e16053f9fba5b1ef75b76eab82370c3264ee6263"
Je n'arrive pas à l'expliquer ...
Merci beaucoup pour vos réponses.
G.
Penses-tu à une augmentation du cache côté matériel, OS ou postgres (si c'est possible bien sûr) ?
Merci à toi gleu.
Edit : je viens changer la valeur de effective_cache_size à 1/4 de ma ram (4 Go). Aucun changement flagrant sur la durée d'exécution des requêtes à froid.
Au temps pour moi. Chose faite :
model_gfs_025=> select * from pg_statio_user_indexes;
relid | indexrelid | schemaname | relname | indexrelname | idx_blks_read | idx_blks_hit
-------+------------+------------+--------------+-----------------+---------------+--------------
24592 | 24605 | public | last_run_025 | lat_lng_gfs_025 | 5708574 | 85
(1 ligne)
model_gfs_025=> select * from pg_statio_user_tables;
relid | schemaname | relname | heap_blks_read | heap_blks_hit | idx_blks_read | idx_blks_hit | toast_blks_read | toast_blks_hit | tidx_blks_read | tidx_blks_hit
-------+------------+--------------+----------------+---------------+---------------+--------------+-----------------+----------------+----------------+---------------
24592 | public | last_run_025 | 23970250 | 22113815 | 5708574 | 85 | | | |
(1 ligne)
En théorie gleu, les utilisateurs vont se connecter de partout vu que c'est une application mobile à destination du grand public ... Du coup, la plus part du temps le cache sera à froid comme tu le dis.
Les lignes sont en effet très petites.
Je ne sais pas si c'est ce que tu attends, mais voici les infos :
model_gfs_025=> select * from pg_statio_user_indexes;
relid | indexrelid | schemaname | relname | indexrelname | idx_blks_read | idx_blks_hit
-------+------------+------------+--------------+-----------------+---------------+--------------
24592 | 24605 | public | last_run_025 | lat_lng_gfs_025 | 16 | 15
model_gfs_025=> select * from pg_statio_user_tables;
relid | schemaname | relname | heap_blks_read | heap_blks_hit | idx_blks_read | idx_blks_hit | toast_blks_read | toast_blks_hit | tidx_blks_read | tidx_blks_hit
-------+------------+--------------+----------------+---------------+---------------+--------------+-----------------+----------------+----------------+---------------
24592 | public | last_run_025 | 21934277 | 20803384 | 16 | 15 | | | |
Bonsoir,
Après de multiples soucis, le serveur en version 9.4 est en prod !
Voici le résultat de ta demande gleu :
model_gfs_025=> EXPLAIN (ANALYZE, BUFFERS) select * from last_run_025 where latitude = 57.50 and longitude = 33.25;
QUERY PLAN
------------------------------------------------------------------------------------------------------------------------------------------
Index Scan using lat_lng_gfs_025 on last_run_025 (cost=0.57..1351.22 rows=334 width=67) (actual time=22.499..1539.051 rows=238 loops=1)
Index Cond: ((latitude = 57.5::double precision) AND (longitude = 33.25::double precision))
Buffers: shared read=243
Planning time: 18.287 ms
Execution time: 1539.456 ms
(5 lignes)
En voici un autre avec des coordonnées différentes :
model_gfs_025=> EXPLAIN (ANALYZE, BUFFERS) select * from last_run_025 where latitude = 51.50 and longitude = 36.25;
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------------------
Index Scan using lat_lng_gfs_025 on last_run_025 (cost=0.57..876.89 rows=217 width=67) (actual time=15.236..1364.727 rows=238 loops=1)
Index Cond: ((latitude = 51.5::double precision) AND (longitude = 36.25::double precision))
Buffers: shared hit=2 read=241
Planning time: 0.210 ms
Execution time: 1364.885 ms
(5 lignes)
Merci à tous en tout cas pour vos aides. Il me reste maintenant à comprendre pourquoi la requête prend 1.5s et comment diminuer ce coût sans changer de serveur.
Alors que voudrait dire : psql:processing/db/2_db.sql:37206258: mémoire épuisée ? Sachant que la mémoire serveur n'est pas toute utilisée ... Je vais continuer mes investigations
Bonsoir rjuju,
Merci de ton conseil. Elles paraissent correctes (vérification visuel et applicatif). Néanmoins, s'il existe un outil postgres pour faire une vérification global (une sorte de checksum ) je suis preneur. Encore merci.
Je me retrouve confronté à un soucis de performance lors de mes ajouts en masse avec COPY, où le serveur me retourne un :
Mémoire épuisée
Assez étrange d'ailleurs, car 2 fichiers sont passés auparavant, là il bloque sur le 3ème (même taille que les autres, ~3.3Go et ~60 000 000 lignes). J'ai augmenté le shared_buffers à 3Go (j'ai 16Go de ram), mais aucun changement.
Edit : merci à toi gleu, je vais procéder ainsi.
Bonsoir,
Après un très fort crash du serveur en prod, les fichiers de journalisation de la version 8.4 ont été perdu ...
Starting PostgreSQL 8.4 database server: mainThe PostgreSQL server failed to start. Please check the log output: 2015-02-12 19:06:55 CET LOG: le système de bases de données a été arrêté à 2015-02-12 18:22:32 CET 2015-02-12 19:06:55 CET LOG: n'a pas pu ouvrir le fichier « pg_xlog/00000001000001280000000F » (journal de transactions 296, segment 15) : Aucun fichier ou dossier de ce type 2015-02-12 19:06:55 CET LOG: enregistrement du point de vérification primaire invalide 2015-02-12 19:06:55 CET LOG: n'a pas pu ouvrir le fichier « pg_xlog/00000001000001280000000F » (journal de transactions 296, segment 15) : Aucun fichier ou dossier de ce type 2015-02-12 19:06:55 CET LOG: enregistrement du point de vérification secondaire invalide 2015-02-12 19:06:55 CET PANIC: n'a pas pu localiser un enregistrement d'un point de vérification valide 2015-02-12 19:06:55 CET LOG: processus de lancement (PID 16539) a été arrêté par le signal 6 : Aborted 2015-02-12 19:06:55 CET LOG: annulation du démarrage à cause d'un échec dans le processus de lancement ... failed!
failed!
Existe t-il un moyen pour relancer la base sans eux ?
La version 9.4 a été installée, la restauration est à cette heure finie pour le problème de ce topic. Il me reste à poser l'INDEX btree. Cependant, avant toutes autres choses, j'aimerai pouvoir refaire partir le 8.4 ... rhaaa (j'ai bien peur que ce ne soit pas possible ...)
Edit : je mets la solution au problème de fichiers de journalisation corrompu
pg_resetxlog /var/lib/postgresql/8.4/main/
Cela ré-initialise ces fichiers, la base peut alors se relancer. (En tant qu'admin gleu, n'hésites pas à me demander d'ouvrir un autre topic pour poster ce bug particulier, si cela peut aider plus de monde).
Bonsoir gleu,
Réponse plus que rapide (réponse à froid, sans recherche préalable), j'ai une erreur de syntaxe sur ta requête.
ERREUR: erreur de syntaxe sur ou près de « ANALYZE »
LIGNE 1 : EXPLAIN (ANALYZE, BUFFERS) select * from last_run_025 where ...
J'éditerai après recherche si je trouve pourquoi
Edit 1 : version postgres 8.4 (okay, ma version est assez vieille j'en conviens )
Edit 2 : les buffers ne sont disponibles que depuis la version 9 ... Le serveur tournant sur la version 6 de Debian je ne peux mettre à jour automatiquement postgres (seule la version 8.4 est dans les dépôts de cette version) sans le compiler et le processus de compilation implique de transférer les anciennes bases. Ce processus est plus que lourd. Je vais reconsidérer le problème et reviens dès que j'ai une solution convenable.
Bonjour gleu et encore merci,
Ne pouvant pas changer mes ressources matériels pour le moment, l'idée du partitionnement m'était venue à la tête. Car une requête brute sur cette table (non partitionnée) donne un temps d'exécution de :
Temps=# select * from last_run_025 where latitude = 57.50 and longitude = 33.25;
Temps : 1552,946 ms
Brute = le première fois, la fois suivante, il organise (normal et heureusement) les données pour me les ressortir beaucoup plus rapide (avec les mêmes lat/lng).
Le soucis vient du fait que jamais ces lat/lng ne seront les mêmes. Elles sont rattachées à la localisation des utilisateurs, et les utilisateurs seront partout (app mobile).
Les données couvrent la surface terrestre, partitionner cette zone en sous-zones et créer une table pour chaque zone permettrait de diviser les temps d'exécution par autant non ? Imaginons 100 zones lat/lng, lors d'un select user, la requête ne sera effectuée que sur la table de la zone, donc sur 2,5 millions de lignes (250 millions / 100). Est-ce que le gain est trop faible par rapport à une unique table ? La création de 100 ou 1000 tables, une par zone, m'ennuie aussi, car je trouve ça un peu "sale" ... Mais plus d'1,5 s pour un select c'est long, très long. Même pour 250 millions de lignes ça me parait long avec un btree sur lat/lng ... Surtout après ta remarque "250 pauvres millions de lignes"
Que de questions, j'en conviens, désolé gleu
Réponse ultra rapide, c'est top ! Merci à toi gleu
Ci-dessous, un count des deux premières requêtes.
//select count(*) from last_run_025 where latitude = -26 and longitude = 359.75;
// count 238
//select count(*) from last_run_025 where latitude = -34 and longitude = 339.75;
// count 238
Et comme indiqué dans mon précédent post, j'obtiens :
// (cost=0.00..918.66 rows=218 width=71) (actual time=0.050..1.284 rows=238 loops=1)
et
// (cost=0.00..1859.32 rows=451 width=71) (actual time=0.058..1.115 rows=238 loops=1)
Le premier rows est bien doublé comme tu l'as indiqué gleu, mais pas le "real" (si j'ai bien compris).
En tout état de cause, le nbre de lignes retourné est bien identique pour les deux requêtes. Du coup, où se fait la différence de coût ? ...
Mes excuses si j'ai du mal à tout comprendre et un grand merci pour ton aide.
=> A raison de 250 millions de lignes indexées sur une seule table, je me demande le gain de performances à la spliter entre plusieurs tables en fonction des lat/lng ...
Au passage, penses-tu que le gain serait intéressant ?
Encore merci gleu !
Toujours pour le même environnement, avec l'outil ANALYSE et EXPLAIN j'ai ceci :
// Temps=# explain analyse select * from last_run_025 where latitude = -26 and longitude = 359.75;
// Index Scan using lat_lng_idx on last_run_025 (cost=0.00..918.66 rows=218 width=71) (actual time=0.050..1.284 rows=238 loops=1)
// Index Cond: ((latitude = (-26)::double precision) AND (longitude = 359.75::double precision))
// Total runtime: 1.340 ms
// Temps=# explain analyse select * from last_run_025 where latitude = -34 and longitude = 339.75;
// Index Scan using lat_lng_idx on last_run_025 (cost=0.00..1859.32 rows=451 width=71) (actual time=0.058..1.115 rows=238 loops=1)
// Index Cond: ((latitude = (-34)::double precision) AND (longitude = 339.75::double precision))
// Total runtime: 1.162 ms
Sur ma table, j'ai un index btree(latitude, longitude).
Pourquoi je n'ai pas le même coût entre les deux requêtes ? Serait-il plus performant d'avoir une clé de hash (lat+lng, mais non unique du coup) et de l'indexer seule ?
Idem, ci-dessous (les deux requêtes n'ont jamais été effectuées auparavant) :
// Temps=# explain analyse select * from last_run_025 where latitude = -34 and longitude = 300.75;
// Index Scan using lat_lng_idx on last_run_025 (cost=0.00..1224.16 rows=293 width=71) (actual time=12.852..1497.365 rows=238 loops=1)
// Index Cond: ((latitude = (-34)::double precision) AND (longitude = 300.75::double precision))
// Total runtime: 1497.595 ms
// Temps=# explain analyse select * from last_run_025 where latitude = -34 and longitude = 200.75;
// Index Scan using lat_lng_idx on last_run_025 (cost=0.00..1742.74 rows=422 width=71) (actual time=16.308..1560.096 rows=238 loops=1)
// Index Cond: ((latitude = (-34)::double precision) AND (longitude = 200.75::double precision))
// Total runtime: 1560.307 ms
Pourquoi le coût diffère ? Pourquoi le temps d’exécution est-il aussi important d'un coup ? Il est alors assez difficile de mesurer les performances pour les améliorer ...
A raison de 250 millions de lignes indexées sur une seule table, je me demande le gain de performances à la spliter entre plusieurs tables en fonction des lat/lng ...
Merci pour vos futures réponses qui m'aident grandement !
Bonne fin de journée à tous.
Merci gleu pour tes réponses.
Écrire dans la bonne partition, c'est déjà le cas je crois, car ma base et mon programme tourne sur la même partition (si j'ai bien compris ta question ).
Bien vu pour l'API C++ ! Je vais essayer ça oui.
Merci de tes conseils.
Merci pour ta réponse gleu.
Mais du coup, quelle serait la meilleure solution ? Car je comptais utiliser les triggers pour spliter mes données automatiquement. Ce qui, par la suite, permettrait d'accélérer les vitesses d'accès.
J'avoue que je n'ai plus de solutions. Dans un monde "tout rose", serait-il possible d'écrire directement depuis le C++ les données en "format" postgres ? Ce qui éviterait l'écriture dans un fichier préalable pour ensuite les insérer dans la base. Mais est-ce que le gain sera intéressant ?
Pour te répondre anayrat, je ne peux pas changer mon environnement matériel
Merci à tous pour vos aides.
Bonjour,
Merci à tous pour vos conseils. J'ai mise en place la technique de découpage des fichiers SQL en plusieurs bouts pour pouvoir lancer des COPY en parallèles. Ça prend encore du temps, mais c'est mieux.
Je viens redemander conseil, toujours pour les mêmes travaux, mais maintenant de façon générale.
Question : quel est la meilleure ligne à suivre pour l'environnement ci-dessous (la question est large volontairement) :
Sur un serveur "4 cores 16go ram sata 2 en disque", je dois enregistrer, à raison de 4 fois par jour, ~250 millions de lignes (données météorologiques, donc juste clé, valeur, lat, lng, date). Soit un total ~1 milliard de lignes / jour. Il faut que l'enregistrement soit le plus rapide possible, afin que les données soient à disposition de tous. La récupération de ces données, par la suite, (select) doit également être très rapide, car à destination d'applications mobiles.
Comment vous procéderiez ? Quelle architecture ? Etc.
Mon idée première : découper mes données, que ce soit aussi bien pour l'insert (permettant de paralléliser les COPY), que pour peupler ma base. Je serai partant pour peupler ma base dans de multiples tables (~2000), à l'aide de trigger par exemple, afin que lors de select, avec les latitudes et longitudes (chaque données est rattaché à ce couple) les valeurs soient directement prises dans la bonne table.
Qu'en pensez-vous ?
Un grand merci pour vos conseils en tout cas !
Bonne soirée à tous.
Merci rjuju pour ta réponse.
Lorsque tu dis "mais passer le paramètre fsync à on changera la donne", tu sous-entends quoi ? Que cela va ralentir le processus ?
Je vais voir pour faire plusieurs fichiers et les lancer parallèlement du coup.
Je suis toujours preneur de conseils et d'optimisation ! ;p
PS : n'y a t'il pas moyen (en C++) de sortir un format qui serait plus rapide à être inséré dans la base ?
Multi-thread surement, multi-core très bonne question kenrio !
A moins que mes logs serveur me jouent des tours, je n'ai qu'un cœur qui est utilisé pour le COPY ...
Bonjour à tous,
Voici mon soucis : Je génère ~250 millions de lignes 4 fois par jour, via un script C++ (je passe les détails inutiles ). Ces lignes sont générées au format plat, avec COPY. Lorsque celles-ci sont écrites, j’exécute le fichier via psql pour l'insérer en bloc sur ma base. Le problème se laisse entrevoir, l'insertion en bd prend du temps ... En soit, pas forcément, mais j'aimerai que ça aille bcp plus vite (sans changer de serveur ). Il faut ~25min pour l'ensemble des lignes, soit ~160k lignes / seconde.
Comment procéder autrement et améliorer ces valeurs ? L'outil pg_restore pourrai m'aider avec l'option permettant l'exécution sur plusieurs cœurs, mais je ne vois pas comment sortir un format qui pourrait lui convenir depuis du C++.
Petites précisions, la table n'a aucune contrainte, et j'ai comme configuration celle ci-dessous :
fsync = off
synchronous_commit = off
commit_delay = 50000
checkpoint_segments = 500
checkpoint_timeout = 1h
Les logs me sortent, même avec un checkpoint à 500, un warning m'indiquant de l'augmenter encore.
Que vous dire de plus ... Le serveur est un :
Modèle: DELL® PowerEdge R210
Processeur: 1x Intel® Xeon® L3426
Architecture: 4x 1.86GHz, 64 Bits, VT
RAM: 16 Go DDR3 ECC
Disque dur: 2 x 2 To SATA2 RAID
Merci d'avance pour vos conseils.
Bonne fin de vendredi à tous !
Guillaume.
Pages : 1