Wir haben kürzlich einen Zustrom von Nutzern und einen Traffic-Anstieg verzeichnet, was zu mehr gleichzeitig durchgeführten Suchanfragen geführt hat.
Wir beobachten zunehmend Such-Timeouts bei etwa 1,2 Millionen Beiträgen.
Wie gehen größere Foren im Bereich Suche vor? Haben Sie die Kern-Suchfunktion von Discourse verlassen oder funktioniert sie noch gut? Vielleicht haben Sie den Suchalgorithmus/die Suchabfragen angepasst, um restriktiver/spezifischer zu sein? Datenbank-Optimierung?
Wie sehen Ihre Server-Spezifikationen aus und welche Ressourcen scheinen am stärksten begrenzt zu sein?
Ich prüfe derzeit die Möglichkeit, ein Board mit etwa 20 Millionen Beiträgen (öffentliche Beiträge + private Nachrichten) zu migrieren, und bin daher sehr daran interessiert, mehr über potenzielle Leistungsprobleme bei großen Boards zu erfahren.
Der Weg von 1 Million auf 20 Millionen Beiträge ist lang, sodass es nur wenige Ratschläge gibt, die für euch beide gleichermaßen gelten. Nur als Hinweis: Ich betreibe eine Website mit 9 Millionen Beiträgen, die auf einem i7-7500U @ 2,7 GHz mit 16 GB RAM eine akzeptable Leistung bietet. Auf demselben Server laufen noch einige weitere Websites mit geringerem Aufkommen.
Eine Website, die eine AWS-Datenbank mit 8 GB RAM nutzt und 4 Millionen Beiträge hat, hat insbesondere bei Suchanfragen gewisse Schwierigkeiten.
@Jumanji, wie lauten die Spezifikationen eures Servers?
Wir nutzen AWS. Die Foren laufen auf 4 Instanzen, meiner Erinnerung nach t3.large, also jeweils 4 vCPUs und 16 GB RAM. Wir betreiben Kubernetes auf einem benutzerdefinierten Docker-Image. Unsere Datenbank läuft auf einer separaten Instanz vom Typ m4.large, also 2 vCPUs und 8 GB RAM. Der RAM auf den Datenbankinstanzen könnte definitiv der Flaschenhals sein.
Die Abfragen, die ein Timeout verursachen, beziehen sich im Allgemeinen auf allgemeinere Begriffe, einzelne Wörter. Manche liefen länger als 60 Sekunden. Außerdem haben wir im letzten Monat einen Anstieg des Traffics auf unserer Website verzeichnet. Im Vergleich zum Vormonat ist der Traffic im letzten Monat um 40 % gestiegen. In diesem Zeitraum sind wir zudem von v1.9 auf v2.4 gewechselt. Seit Version 1.9 hat die Suchfunktion die Autovervollständigung hinzugefügt, was ich als zusätzliche Belastung für den Datenbankserver ansehe.
Wir haben eine Abfrageanalyse durchgeführt, und die folgende Abfrage lief zwischen 20 und 60 Sekunden:
`SELECT "posts".*
FROM "posts"
JOIN (
SELECT *, row_number() over() row_number
FROM (
SELECT topics.id, min(posts.post_number) post_number
FROM "posts"
INNER JOIN "post_search_data" ON "post_search_data"."post_id" = "posts"."id"
INNER JOIN "topics" ON "topics"."id" = "posts"."topic_id" AND ("topics"."deleted_at" IS NULL)
LEFT JOIN categories ON categories.id = topics.category_id
WHERE
("posts"."deleted_at" IS NULL)
AND "posts"."post_type" IN (1, 2, 3)
AND (topics.visible)
AND (topics.archetype <> 'private_message')
AND (post_search_data.search_data @@ TO_TSQUERY('english', '''a'':*ABD & ''price'':*ABD'))
AND (categories.id NOT IN (SELECT categories.id WHERE categories.search_priority = 1))
AND ((categories.id IS NULL) OR (NOT categories.read_restricted))
GROUP BY topics.id
ORDER BY
MAX((
TS_RANK_CD(
post_search_data.search_data,
TO_TSQUERY('english', '''a'':*ABD & ''price'':*ABD'),
1|32
) * (
CASE categories.search_priority
WHEN 2
THEN 0.6
WHEN 3
THEN 0.8
WHEN 4
THEN 1.2
WHEN 5
THEN 1.4
ELSE
CASE
WHEN topics.closed
THEN 0.9
ELSE 1
END
END
)
)) DESC,
topics.bumped_at DESC
LIMIT 6
OFFSET 0
) xxx
) x ON x.id = posts.topic_id AND x.post_number = posts.post_number
WHERE ("posts"."deleted_at" IS NULL)
ORDER BY row_number;
---
Sort (cost=495214.55..495214.56 rows=1 width=1177) (actual time=20529.725..20529.727 rows=6 loops=1)
Sort Key: (row_number() OVER (?))
Sort Method: quicksort Memory: 29kB
-> Nested Loop (cost=495164.08..495214.54 rows=1 width=1177) (actual time=20525.899..20529.703 rows=6 loops=1)
-> WindowAgg (cost=495163.65..495163.80 rows=6 width=16) (actual time=20520.976..20521.078 rows=6 loops=1)
-> Limit (cost=495163.65..495163.66 rows=6 width=24) (actual time=20520.969..20521.063 rows=6 loops=1)
-> Sort (cost=495163.65..495232.24 rows=27438 width=24) (actual time=20520.967..20520.969 rows=6 loops=1)
Sort Key: (max((ts_rank_cd(post_search_data.search_data, '''price'':*ABD'::tsquery, 33) * (CASE categories.search_priority WHEN 2 THEN 0.6 WHEN 3 THEN 0.8 WHEN 4 THEN 1.2 WHEN 5 THEN 1.4 ELSE CASE WHEN topics.closed THEN 0.9 ELSE '1'::numeric END END)::double precision))) DESC, topics.bumped_at DESC
Sort Method: top-N heapsort Memory: 25kB
-> GroupAggregate (cost=493642.90..494671.83 rows=27438 width=24) (actual time=19082.214..20506.763 rows=32951 loops=1)
Group Key: topics.id
-> Sort (cost=493642.90..493711.50 rows=27438 width=400) (actual time=19082.184..19283.907 rows=191436 loops=1)
Sort Key: topics.id
Sort Method: external merge Disk: 77632kB
-> Hash Left Join (cost=36655.60..486646.69 rows=27438 width=400) (actual time=1562.696..18611.724 rows=191436 loops=1)
Hash Cond: (topics.category_id = categories.id)
Filter: (((categories.id IS NULL) OR (NOT categories.read_restricted)) AND (NOT (SubPlan 1)))
-> Gather (cost=36645.63..486471.60 rows=58991 width=400) (actual time=1562.623..18249.349 rows=191436 loops=1)
Workers Planned: 2
Workers Launched: 2
-> Nested Loop (cost=35645.63..479572.50 rows=24580 width=400) (actual time=1556.547..18541.793 rows=63812 loops=3)
-> Hash Join (cost=35645.20..328688.61 rows=157831 width=25) (actual time=1551.912..13356.416 rows=285279 loops=3)
Hash Cond: (posts_1.topic_id = topics.id)
-> Parallel Seq Scan on posts posts_1 (cost=0.00..286245.92 rows=504559 width=12) (actual time=0.280..11249.160 rows=404770 loops=3)
Filter: ((deleted_at IS NULL) AND (post_type = ANY ('{1,2,3}'::integer[])))
Rows Removed by Filter: 21884
-> Hash (cost=33938.80..33938.80 rows=92912 width=17) (actual time=1549.103..1549.103 rows=80351 loops=3)
Buckets: 65536 Batches: 2 Memory Usage: 2557kB
-> Seq Scan on topics (cost=0.00..33938.80 rows=92912 width=17) (actual time=0.010..1492.606 rows=80351 loops=3)
Filter: ((deleted_at IS NULL) AND visible AND ((archetype)::text <> 'private_message'::text))
Rows Removed by Filter: 216751
-> Index Scan using posts_search_pkey on post_search_data (cost=0.43..0.96 rows=1 width=383) (actual time=0.017..0.017 rows=0 loops=855836)
Index Cond: (post_id = posts_1.id)
Filter: (search_data @@ '''price'':*ABD'::tsquery)
Rows Removed by Filter: 1
-> Hash (cost=9.43..9.43 rows=43 width=9) (actual time=0.059..0.059 rows=43 loops=1)
Buckets: 1024 Batches: 1 Memory Usage: 10kB
-> Seq Scan on categories (cost=0.00..9.43 rows=43 width=9) (actual time=0.007..0.045 rows=43 loops=1)
SubPlan 1
-> Result (cost=0.00..0.01 rows=1 width=4) (actual time=0.000..0.000 rows=0 loops=191436)
One-Time Filter: (categories.search_priority = 1)
-> Index Scan using index_posts_on_topic_id_and_post_number on posts (cost=0.43..8.45 rows=1 width=1169) (actual time=1.435..1.435 rows=1 loops=6)
Index Cond: ((topic_id = topics.id) AND (post_number = (min(posts_1.post_number))))
Filter: (deleted_at IS NULL)
Planning time: 3.508 ms
Execution time: 20541.411 ms
(46 rows)`