E / S extrêmement lentes avec des requêtes simples PostgreSQL 8.4.4 sur Centos 5.5

10

Le modèle d'E / S étrange et extrêmement lent que je vois est le suivant (sortie de iostat -dxk 1 /dev/xvdb1):

Device:         rrqm/s   wrqm/s   r/s   w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await  svctm  %util
xvdb1             0.00     0.00  0.99  0.99     7.92     3.96    12.00     1.96 2206.00 502.00  99.41

Device:         rrqm/s   wrqm/s   r/s   w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await  svctm  %util
xvdb1             0.00     0.00  0.00  0.00     0.00     0.00     0.00     1.00    0.00   0.00 100.40

Device:         rrqm/s   wrqm/s   r/s   w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await  svctm  %util
xvdb1             0.00     0.00  0.00  0.00     0.00     0.00     0.00     1.00    0.00   0.00 100.40

Device:         rrqm/s   wrqm/s   r/s   w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await  svctm  %util
xvdb1             0.00     0.00  0.99  0.00     3.96     0.00     8.00     0.99 2220.00 1004.00  99.41

Device:         rrqm/s   wrqm/s   r/s   w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await  svctm  %util
xvdb1             0.00     0.00  0.00  0.00     0.00     0.00     0.00     1.00    0.00   0.00 100.40

Device:         rrqm/s   wrqm/s   r/s   w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await  svctm  %util
xvdb1             0.00     0.99  0.99  0.00     7.92     0.00    16.00     1.14 2148.00 1004.00  99.41

Device:         rrqm/s   wrqm/s   r/s   w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await  svctm  %util
xvdb1             0.00     0.00  0.00  0.00     0.00     0.00     0.00     2.01    0.00   0.00 100.40

Device:         rrqm/s   wrqm/s   r/s   w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await  svctm  %util
xvdb1             0.00     0.00  1.00  1.00     4.00     8.00    12.00     2.01 1874.00 502.00 100.40

Je ne sais pas pourquoi l'utilisation du disque et l'attente sont si élevées, et les taux de lecture / écriture sont si bas. Quelle pourrait en être la raison?

La table interrogée a simplement plusieurs colonnes varchar uniquement, dont une est last_name, qui est indexée (en fait lower(last_name)est indexée). La requête elle-même est simple:

SELECT * FROM consumer_m WHERE lower(last_name) = 'hoque';

Voici la sortie d'explication:

                                           QUERY PLAN                                            
-------------------------------------------------------------------------------------------------
 Bitmap Heap Scan on consumer_m  (cost=2243.90..274163.41 rows=113152 width=164)
   Recheck Cond: (lower((last_name)::text) = 'hoque'::text)
   ->  Bitmap Index Scan on consumer_m_last_name_index  (cost=0.00..2215.61 rows=113152 width=0)
         Index Cond: (lower((last_name)::text) = 'hoque'::text)

Notez également que la base de données est sur auto_vacuum, donc aucun vide / analyse explicite n'a été effectué.

ehsanul
la source
Avez-vous personnalisé votre postgresql.conf? Si CentOS a les mêmes valeurs par défaut que RHEL 5.x, vous aurez peu de mémoire pour les postgres, ce qui pourrait forcer beaucoup d'E / S disque. Quelle est la taille des lignes de ce tableau?
Thiago Figueiro
La table tient dans la mémoire, comme évidemment l'index; il a été partitionné de cette façon. Et postgresql.conf a été convenablement personnalisé (shared_buffers, effective_cache_size, etc.). Même si ce n'était pas le cas, je ne m'attendrais pas à de telles performances dégénérées.
ehsanul

Réponses:

5

Le fait que votre appareil fonctionne /dev/xvdb1implique que vous exécutez sous Xen. Comment est configuré votre stockage? Y a-t-il des conflits pour le périphérique sous-jacent, et à quoi cela iostatressemble - t -il ?

À moins que vous ne puissiez éliminer cela aussi probablement, c'est là que je vais pointer le tourniquet du blâme de mauvaises performances.

Fondamentalement, l'approche globale pour démêler un problème de performances comme celui-ci consiste à penser à toutes les couches où un goulot d'étranglement pourrait se produire, puis à concevoir des tests pour les éliminer jusqu'à ce que vous isoliez le problème.

mattdm
la source
Aucune contention. Bien que vous ayez raison de dire qu'il s'agit d'un serveur virtuel, le disque dur a été entièrement dédié à ce serveur, et je n'exécute qu'une seule requête de base de données à la fois sans aucune autre opération de serveur intensive. Le stockage n'est qu'un seul disque SATA tournant. Notez que j'ai quelques autres serveurs / bases de données (séparés) avec à peu près la même configuration, mais qui fonctionnent rapidement avec un faible E / S, comme prévu, compte tenu des requêtes / indexation similaires.
ehsanul
Pouvez-vous exécuter iostatsur le disque à partir de dom0 juste pour voir si l'image est similaire? Pouvez-vous faire d'autres tests de référence de disque de base des deux niveaux? Cela aidera au moins à préciser où chercher ensuite.
mattdm
Sûr. Pourquoi vous attendez-vous à une différence en fonction de l'endroit où iostatest exécuté? Cela devrait-il être important? Je n'ai pas actuellement d'accès direct à dom0, bien que je puisse l'obtenir. J'essaierai fiopour le benchmarking en attendant.
ehsanul
3
pour une chose: les instantanés peuvent créer une telle situation
Hubert Kario
3
Vous aviez raison mattdm, il y avait des conflits, apparaissant sur dom0. C'était un problème de communication, mon patron avait donné une partie du disque dur à un autre serveur sous la gestion de quelqu'un d'autre, à mon insu. J'avais l'impression qu'il était dédié, car c'est comme ça que nous le configurons toujours. Je suppose que c'est pourquoi il est toujours important de vérifier vos hypothèses. Merci!
ehsanul
1

Voici quelques suggestions, dans un ordre plus ou moins aléatoire:

  1. Autovacum n'est pas activé par défaut dans CentOS. Vous devez définir plusieurs paramètres pour l'activer. Revérifiez pour que le processus sous vide s'exécute réellement. Il est facile de manquer l'un des paramètres requis.

  2. Notez que vous devez effectuer une deuxième étape de filtrage pour cette requête, ce qui peut être coûteux en fonction de ce que vous récupérez. Je considérerais un indice tel que:

    CREATE INDEX consumer_m_lower_last ON consumer_m (inférieur (nom));

    Qui correspondra à votre requête et supprimera la nouvelle vérification.

  3. De plus, comme le souligne mattdm, vous ne pouvez pas faire confiance à iostat dans les environnements virtualisés.

  4. Vous devriez probablement vérifier http://lonesysadmin.net/2008/02/21/elevatornoop/ si vous avez des problèmes d'E / S dans un environnement XEN. Les paramètres de l'ascenseur peuvent avoir un impact, mais pas aussi important.

  5. Le disque sous-jacent utilise-t-il des instantanés LVM? Bien que cela soit très utile du point de vue de la gestion, cela peut tuer les performances d'E / S. Cela est vrai à la fois si le périphérique de bloc que vous utilisez est un instantané et si un instantané a été pris du périphérique de bloc.

pehrs
la source
Merci pour les suggestions. L'index est en fait inférieur (last_name), même si j'ai omis "inférieur" du nom de l'index. Je ne sais donc pas pourquoi il y a une nouvelle vérification. Le disque monté /utilise en fait des instantanés LVM, mais pas celui sur lequel la base de données est stockée. Je ne pense donc pas que ce soit ça. Je vais cependant examiner vos autres suggestions!
ehsanul
1

Je doute que ce soit un problème avec PostgreSQL, et plus probablement un problème avec Disk IO. Comme le mentionnent les commentaires d'une autre réponse, s'il s'agit d'un problème d'E / S de disque, vous devez vraiment mesurer à partir de Dom0 afin d'avoir une image de tout ce qui se passe.

J'ai eu un problème très similaire il y a quelque temps et il s'est avéré être un problème avec le contrôleur de disque. L'accès très lent au disque provoquait un goulot d'étranglement du système en attendant les E / S du disque (ce qui s'est révélé comme des moyennes de charge et des temps d'attente très élevés, mais aussi des processus attendant que le disque consomme plus de CPU qu'ils ne le feraient autrement. Il s'est avéré que le noyau ne reconnaissait pas correctement le contrôleur et retombait sur le contrôleur IDE de la vieille école au lieu d'un contrôleur SATA rapide.

Le correctif consistait à démarrer avec

hda=noprobe hda=none 

à la fin de la chaîne du noyau dans /etc/grub.conf. (Bien sûr, ajoutez tous les disques dont vous disposez, ala: hdc=noprobe, hdc=none, hdd=...)

Jed Daniels
la source
Merci, mais il s'avère que c'était quelque chose de beaucoup plus idiot dans ce cas. Votez quand même.
ehsanul