Question

C'est une question assez longue, veuillez supporter avec moi.

J'aimerais donc d'abord expliquer que j'ai une base de données de journaux de pare-feu créés à l'aide de la commande suivante:

CREATE TABLE firewall_logs_mapped
(
  log_time text,
  log_time_mapped double precision,
  syslog_priority text,
  syslog_priority_mapped double precision,
  operation text,
  operation_mapped double precision,
  message_code text,
  message_code_mapped double precision,
  protocol text,
  protocol_mapped double precision,
  source_ip text,
  source_ip_mapped double precision,
  destination_ip text,
  destination_ip_mapped double precision,
  source_port text,
  source_port_mapped double precision,
  destination_port text,
  destination_port_mapped double precision,
  destination_service text,
  destination_service_mapped double precision,
  direction text,
  direction_mapped double precision,
  connections_built text,
  connections_built_mapped double precision,
  connections_torn_down text,
  connections_torn_down_mapped double precision,
  hourofday text,
  hourofday_mapped double precision,
  meridiem text,
  meridiem_mapped double precision
)

Donc, fondamentalement, pour chaque valeur de la base de données, il existe également une valeur mappée qui est un flotteur représentant la coordonnée y pour la valeur de telle sorte qu'elle puisse être tracée sur un graphique que j'ai configuré.

J'ai également un index sur chacune des colonnes non mappées dans la base de données.

Maintenant, j'ai une interface par laquelle l'utilisateur peut rechercher la base de données en spécifiant le nom et la valeur de la colonne, et le logiciel convertira cela en une requête et interrogez la base de données. C'est-à-dire qu'ils peuvent saisir quelque chose comme:

operation Built

Et le logiciel crée et exécute la requête suivante:

SELECT DISTINCT log_time_mapped, syslog_priority_mapped, 
       operation_mapped, message_code_mapped, protocol_mapped, 
       source_ip_mapped, destination_ip_mapped, 
       source_port_mapped, destination_port_mapped, 
       destination_service_mapped, direction_mapped, 
       connections_built_mapped, connections_torn_down_mapped, 
       hourofday_mapped, meridiem_mapped 
FROM firewall_logs_mapped 
WHERE operation = 'Built'

Maintenant, cette requête particulière n'utilise pas réellement l'indice (vraisemblablement car il renvoie environ 48% des lignes de la base de données) et renvoie 11 426 373 lignes en 126 775 ms. Voici l'explication Analyze pour la requête:

"Seq Scan on public.firewall_logs_mapped  (cost=0.00..1234282.95 rows=11295161 width=120) (actual time=0.357..16139.005 rows=11426373 loops=1)"
"  Output: log_time_mapped, syslog_priority_mapped, operation_mapped, message_code_mapped, protocol_mapped, source_ip_mapped, destination_ip_mapped, source_port_mapped, destination_port_mapped, destination_service_mapped, direction_mapped, connections_built (...)"
"  Filter: (firewall_logs_mapped.operation = 'Built'::text)"
"  Rows Removed by Filter: 12049756"
"Total runtime: 16751.255 ms"

Maintenant, si je comprends bien, il semble que le temps soit consacré à filtrer les données par la clause où. Ce temps peut-il être réduit?

Donc, comme je trace un graphique de coordonnées parallèles, je ne nécessite que les combinaisons uniques des valeurs de colonne renvoyées via la clause WHERE, car sinon il y aura juste beaucoup de lignes décrochées les unes sur les autres.

Comment pourrais-je sélectionner uniquement les combinaisons uniques de colonnes adjacentes? Est-ce une tâche trop compliquée à effectuer via une requête de base de données? Est-ce que cela accélérerait la requête?

SELECT DISTINCT sélectionnera les lignes uniques (combinaisons de toutes les valeurs consécutives), je parle des combinaisons uniques de deux colonnes adjacentes, comme dans les coordonnées parallèles, une ligne est tracée entre les colonnes adjacentes, pour chaque colonne dans une ligne, IE de Log_time à syslog_priority, la ligne suivante de cette ligne sera de syslog_priority à l'opération, etc. Consultez ce lien: http://en.wikipedia.org/wiki/file:parcorfisheriris.png, dans mon cas, chaque axes serait une colonne de la base de données.

Actuellement, je le fais dans Python en utilisant les résultats pour créer un tableau de coordonnées pour les lignes à tracer, puis je traverse le tableau ajoutant les coordonnées de ligne à un ensemble si elle n'est pas vue auparavant dans la boucle.

ÉDITER:

Des index ont été créés comme suit:

CREATE INDEX unique_log_time_index ON unique_firewall_logs_mapped (log_time);
CREATE INDEX unique_syslog_priority_index ON unique_firewall_logs_mapped (syslog_priority);
CREATE INDEX unique_operation_index ON unique_firewall_logs_mapped (operation);
CREATE INDEX unique_message_code_index ON unique_firewall_logs_mapped (message_code);
CREATE INDEX unique_protocol_index ON unique_firewall_logs_mapped (protocol);
CREATE INDEX unique_source_ip_index ON unique_firewall_logs_mapped (source_ip);
CREATE INDEX unique_destination_ip_index ON unique_firewall_logs_mapped (destination_ip);
CREATE INDEX unique_source_port_index ON unique_firewall_logs_mapped (source_port);
CREATE INDEX unique_destination_port_index ON unique_firewall_logs_mapped (destination_port);
CREATE INDEX unique_destination_service_index ON unique_firewall_logs_mapped (destination_service);
CREATE INDEX unique_direction_index ON unique_firewall_logs_mapped (direction);
CREATE INDEX unique_connections_built_index ON unique_firewall_logs_mapped (connections_built);
CREATE INDEX unique_connections_torn_down_index ON unique_firewall_logs_mapped (connections_torn_down);
CREATE INDEX unique_hourofday_index ON unique_firewall_logs_mapped (hourofday);
CREATE INDEX unique_meridiem_index ON unique_firewall_logs_mapped (meridiem);

Ma version PostgreSQL est 9.3, Random_Page_Cost est 4.0, SEQ_PAGE_COST est 1.0.

Je voudrais également dire que j'ai essayé de forcer l'utilisation de l'index et la requête a pris 2 secondes environ que sans l'indice.

Pas de solution correcte

Licencié sous: CC-BY-SA avec attribution
Non affilié à dba.stackexchange
scroll top