Vorige week was ik op mijn werk bezig met een nieuw zoeksysteem te maken op onze website. Ons oude zoeksysteem was geschreven in Perl, niet door mij, en haalde zijn data uit een tekstbestand. Dat systeem was razendsnel.
Al onze producten stonden allemaal al in een database omdat daar het ordersysteem gekoppeld zat. (Het updaten van de producten in de database gebeurde door een bestand uit ons voorraadbeheer pakket te exporteren en dat vervolgens inlezen in de database.
) Het idee was daarom om een PHP script te maken wat netjes opzocht in de database en de producten netjes per 20 weergaf. Daar zat het probleem niet.
Hier onder een overzicht hoe de tabel products is opgebouwd (Nee, er is inderdaad geen veld met een auto_increment of sequence. Dit deed het voorraadbeheer pakket):

Deze tabel had deze index:
Toen ik bezig was met het schrijven van het ordersysteem kwam ik echter een performance probleem tegen. Het opzoeken van data in de database duurde nogal lang. Een simpele query als
Omdat ik nog wat velden wilde toevoegen aan de tabel en de data een aantal keer opnieuw moest inlezen in de tabel had ik een kopie gemaakt om daarin te doen wat ik wilde. Deze tabel heb ik aangemaakt met:
Vervolgens heb ik de index aangemaakt en wat schetst mijn verbazing? De query uitvoeren kostte nog maar 70 milliseconden.
Uiteindelijk heb ik besloten voor het paardenmiddel. De tabel products kopieren, droppen en weer terugzetten. Indexen aanmaken en klaar. Zo gezegd, zo gedaan.
En inderdaad, toen werkte de andere tabel ook snel. Nu draait het nieuwe zoeksysteem al twee dagen en nog steeds geen performance problemen gezien.
Alleen, ik zit nog steeds met een vraag. Hoe kan het dat een tabel in PostgreSQL sneller wordt als er een kopie van aangemaakt wordt? De tabellen waren exact hetzelfde, alleen de tabel products was ongeveer 10 keer trager dan products_backup.
Heeft er iemand een idee?
Al onze producten stonden allemaal al in een database omdat daar het ordersysteem gekoppeld zat. (Het updaten van de producten in de database gebeurde door een bestand uit ons voorraadbeheer pakket te exporteren en dat vervolgens inlezen in de database.

Hier onder een overzicht hoe de tabel products is opgebouwd (Nee, er is inderdaad geen veld met een auto_increment of sequence. Dit deed het voorraadbeheer pakket):

Deze tabel had deze index:
SQL:
1
| CREATE INDEX id_products_key ON products USING btree (id) |
Toen ik bezig was met het schrijven van het ordersysteem kwam ik echter een performance probleem tegen. Het opzoeken van data in de database duurde nogal lang. Een simpele query als
SQL:
kostte al 700 milliseconden.1
| SELECT id FROM products WHERE title ~* 'Zoekstring' OR description ~* 'Zoekstring' LIMIT 20 OFFSET 0 |
Omdat ik nog wat velden wilde toevoegen aan de tabel en de data een aantal keer opnieuw moest inlezen in de tabel had ik een kopie gemaakt om daarin te doen wat ik wilde. Deze tabel heb ik aangemaakt met:
SQL:
1
| CREATE TABLE products_test AS SELECT * FROM products |
Vervolgens heb ik de index aangemaakt en wat schetst mijn verbazing? De query uitvoeren kostte nog maar 70 milliseconden.
Uiteindelijk heb ik besloten voor het paardenmiddel. De tabel products kopieren, droppen en weer terugzetten. Indexen aanmaken en klaar. Zo gezegd, zo gedaan.
SQL:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| BEGIN; -- Tabel kopieren CREATE TABLE products_backup AS SELECT * FROM products; -- Andere tabel droppen DROP TABLE products; -- Nieuwe tabel aanmaken aan de hand van back-up tabel CREATE TABLE products AS SELECT * FROM products_backup; -- Index aanmaken CREATE INDEX id_products_key ON products USING BTREE(id); -- Backup tabel verwijderen DROP TABLE products_backup; COMMIT; |
En inderdaad, toen werkte de andere tabel ook snel. Nu draait het nieuwe zoeksysteem al twee dagen en nog steeds geen performance problemen gezien.
Alleen, ik zit nog steeds met een vraag. Hoe kan het dat een tabel in PostgreSQL sneller wordt als er een kopie van aangemaakt wordt? De tabellen waren exact hetzelfde, alleen de tabel products was ongeveer 10 keer trager dan products_backup.
Heeft er iemand een idee?