sql >> Database >  >> RDS >> PostgreSQL

Query-optimalisatie in PostgreSQL. UITLEG Basis - Deel 1

Waarom kost het zoveel tijd om een ​​query uit te voeren? Waarom zijn er geen indexen? De kans is groot dat je hebt gehoord over EXPLAIN in PostgreSQL. Er zijn echter nog steeds veel mensen die geen idee hebben hoe ze het moeten gebruiken. Ik hoop dat dit artikel gebruikers zal helpen deze geweldige tool aan te pakken.

Dit artikel is de auteursrevisie van Understanding EXPLAIN door Guillaume Lelarge. Aangezien ik wat informatie heb gemist, raad ik je ten zeerste aan om kennis te maken met het origineel.

De duivel is niet zo zwart als hij is geschilderd

Het is belangrijk om de logica van de PostgreSQL-kernel te begrijpen om query's te optimaliseren. Ik zal het proberen uit te leggen. Het is echt niet zo ingewikkeld.

EXPLAIN toont de nodige informatie die uitlegt wat de kernel doet voor elke specifieke zoekopdracht.

Laten we eens kijken naar wat de EXPLAIN-opdracht weergeeft en begrijpen wat er precies gebeurt in PostgreSQL. U kunt deze informatie toepassen op PostgreSQL 9.2 en hogere versies.

Onze taken:

  • Leer hoe u de uitvoer van het EXPLAIN-commando kunt lezen en begrijpen
  • Begrijp wat er gebeurt in PostgreSQL wanneer een query wordt uitgevoerd

Eerste stappen

We zullen oefenen op een testtafel met een miljoen rijen.

CREATE TABLE foo (c1 integer, c2 text);
INSERT INTO foo
  SELECT i, md5(random()::text)
  FROM generate_series(1, 1000000) AS i;

Probeer de gegevens te lezen

EXPLAIN SELECT * FROM foo;

Het is op verschillende manieren mogelijk om gegevens uit een tabel te lezen. In ons geval meldt EXPLAIN dat een Seq Scan wordt gebruikt - een sequentiële, blok-voor-blok, uitgelezen Foo-tabelgegevens.

Wat is kosten ?

Nou, het is geen tijd, maar een concept dat is ontworpen om de kosten van een operatie te schatten. De eerste waarde 0,00 zijn de kosten voor het verkrijgen van de eerste rij. De tweede waarde 18334.00 zijn de kosten voor het verkrijgen van alle rijen.

Rijen zijn het geschatte aantal rijen dat wordt geretourneerd wanneer een Seq Scan-bewerking wordt uitgevoerd. De planner retourneert deze waarde. In mijn geval komt het overeen met het werkelijke aantal rijen in de tabel.

Breedte is een gemiddelde grootte van één rij in bytes.

Laten we proberen 10 rijen toe te voegen.

INSERT INTO foo
  SELECT i, md5(random()::text)
  FROM generate_series(1, 10) AS i;
EXPLAIN SELECT * FROM foo;

De waarde van rijen is niet gewijzigd. De statistieken van de tabel zijn oud. Roep de opdracht ANALYZE op om de statistieken bij te werken.

Nu, rijen het juiste aantal rijen weergeven.

Wat gebeurt er bij het uitvoeren van ANALYSE?

  • Willekeurig worden een aantal rijen geselecteerd en uit de tabel gelezen.
  • De statistieken van waarden per kolom worden verzameld.

Het aantal rijen dat ANALYZE leest, hangt af van de parameter default_statistics_target.

Werkelijke gegevens

Alles wat we hierboven in de uitvoer van het EXPLAIN-commando zagen, is wat de planner verwacht te krijgen. Laten we proberen ze te vergelijken met de resultaten op werkelijke gegevens. Gebruik hiervoor EXPLAIN (ANALYSE).

EXPLAIN (ANALYZE) SELECT * FROM foo;

Een dergelijke zoekopdracht zal inderdaad worden uitgevoerd. Dus als u EXPLAIN (ANALYZE) uitvoert voor de INSERT-, DELETE- of UPDATE-instructies, worden uw gegevens gewijzigd. Doe voorzichtig! Gebruik in deze gevallen de opdracht ROLLBACK.

De opdracht geeft de volgende aanvullende parameters weer:

  • werkelijke tijd is de werkelijke tijd in milliseconden die zijn besteed aan respectievelijk de eerste rij en alle rijen.
  • rijen is het werkelijke aantal rijen dat is ontvangen met Seq Scan.
  • loops is het aantal keren dat de Seq Scan-bewerking moest worden uitgevoerd.
  • Totale runtime is de totale tijd van het uitvoeren van query's.

Verder lezen:

Query-optimalisatie in PostgreSQL. UITLEG Basisprincipes – Deel 2

Query-optimalisatie in PostgreSQL. UITLEG Basisprincipes – Deel 3


  1. Fout tijdens het verzenden van QUERY-pakket

  2. Hoe MySQL-database te verbinden met PHP-website

  3. hoe een tabelnaam als parameter doorgeven aan de opgeslagen procedure?

  4. Hoe UTC_TIMESTAMP() werkt in MariaDB