Outdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchPC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Test PostgreSQL full-text search on two separate tracks: load-test the real search query against representative data to measure performance, and judge its returned results against an application-specific set of relevant answers. A fast query is not necessarily a useful one, and a higher ts_rank score is not a universal measure of relevance.
What you need to measure
Performance testing answers whether the system can serve the search workload at the concurrency and arrival rate your product expects. Relevance testing answers whether users see the right documents, in the right order, for representative queries. Keep the datasets, query mix, and configuration consistent when comparing changes, but evaluate the two outcomes independently.
As an Amazon Associate I earn from qualifying purchases.
PostgreSQL’s documentation describes relevance as vague and application-specific. Its built-in ranking functions are tools to adapt and evaluate, not a universal relevance formula. PostgreSQL 18: Controlling Text Search
Freeze the conditions before comparing runs
A search result depends on more than the index. PostgreSQL turns documents into tsvector values and search input into tsquery values; the text-search configuration determines token parsing and dictionary normalization. Stop words, stemming, and other dictionary behavior can affect what matches. If configuration changes between runs, you may be measuring a different search rather than a faster version of the same one. PostgreSQL 18: Full Text Search
#1 Best Overall
Record the conditions that define each experiment:
- PostgreSQL major version and relevant settings.
- Text-search configuration and how vectors are constructed, including field weights and null handling.
- Index definition and the data snapshot, including its size and composition.
- The actual SQL, parameter values, filters, query mix, and result limit.
- Client count, target transaction rate, cache and warm-up conditions, and the latency and throughput observed.
Use the same data and environment for baseline and comparison runs, then change one variable at a time. Plan estimates are approximate, and actual performance depends on the platform and data statistics; present results as measurements from the tested environment, not as universal PostgreSQL limits. PostgreSQL 18: Using EXPLAIN
Check what your documents and queries mean to PostgreSQL
Before timing search, inspect sample documents after vectorization and sample queries after parsing. Confirm that the tokens, stop words, and normalized forms match the behavior your product intends. PostgreSQL provides functions for inspecting text-search parsing and dictionary behavior; the full-text search documentation describes the configuration and representation model. PostgreSQL 18: Full Text Search
Make nullable fields explicit when composing a vector. For example, an illustrative vector expression for a nullable title and body can use coalesce:
Rank #2
setweight(to_tsvector('english', coalesce(title, '')), 'A') ||
setweight(to_tsvector('english', coalesce(body, '')), 'D')
The configuration and weights here are examples, not a prescription: use the configuration appropriate to the text and verify the resulting vectors. If title matches should contribute differently from body matches, use weighted vectors and ensure the query’s ranking expression actually uses them. PostgreSQL’s text-search controls documentation explains vector weights, ranking, and normalization. PostgreSQL 18: Controlling Text Search
Choose an index, then inspect the actual plan
GIN is the documented preferred starting point for frequent full-text searches. GiST is another supported option, but its signatures are lossy and may return false matches that PostgreSQL must recheck against the row. GIN stores lexemes rather than vector weight labels, so weighted searches may also require heap-row rechecks. Those implementation differences do not establish which index will be faster for your data or update workload: measure the real query and inspect its plan. The index behavior described here is from the PostgreSQL 16 index documentation; check the documentation for the major version you deploy. PostgreSQL 16: Preferred Index Types for Text Search
| Index | Documented behavior | What to examine in your workload |
|---|---|---|
| GIN | Preferred text-search index type; stores lexemes, not vector weight labels, so weighted searches may need heap-row rechecks. | Index size and build cost, recheck and heap activity, search latency, and the effect of updates. |
| GiST | Uses lossy signatures and can produce false matches that PostgreSQL checks against rows. | Index size and build cost, false-match and heap activity, search latency, and the effect of updates. |
Run EXPLAIN (ANALYZE, BUFFERS) on the actual search statement with representative parameters. For example, adapting table and column names to your schema:
Rank #3
EXPLAIN (ANALYZE, BUFFERS)
SELECT id
FROM documents
WHERE search_vector @@ plainto_tsquery('english', 'example terms')
ORDER BY ts_rank(search_vector, plainto_tsquery('english', 'example terms')) DESC
LIMIT 20;
ANALYZE executes the statement and reports actual timings and row counts alongside estimates. Read the plan tree for the scan type, row estimates versus actual rows, rechecks, sorts, and buffer activity. An index is not guaranteed to be the right plan for every dataset or query selectivity. Planner costs are estimates in relative cost units, not elapsed-time promises; actual timing and buffer evidence from your environment are the useful observations. PostgreSQL 18: Using EXPLAIN
Load-test the search transaction, not a generic database workload
Use a custom pgbench script that runs the production search statement, with representative terms, filters, limits, and ranking. The built-in workload is not a substitute for your application’s search mix. Vary client concurrency and, separately, the target transaction rate so you can see how the system behaves as demand changes. PostgreSQL’s pgbench supports custom scripts and rate control. PostgreSQL 18: pgbench
For a script named search.sql, a rate-controlled run can be started with a command such as:
pgbench -f search.sql -c 32 -j 8 -T 300 -R 100 dbname
This example runs 32 clients with 8 worker threads for 300 seconds at a scheduled rate of 100 transactions per second. Those are illustrative command values, not recommended production settings. Set concurrency and target rate to values that let you explore your own workload and service objectives. The script should use the same SQL shape and result limit as the application, with a deliberate mix of query parameters rather than a single unusually easy term.
Record latency distribution, achieved throughput, failures, and schedule lag, as well as the plan and resource evidence. With rate control, reported latency includes time spent waiting behind the schedule. Rising lag means the test is falling behind its intended arrival rate, even if a simple throughput figure looks acceptable. Interpret --latency-limit carefully: during a rate-controlled run, transactions that would exceed the limit may be skipped rather than sent. Account for skipped work when interpreting the result. PostgreSQL 18: pgbench
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Repeat baseline and changed runs under comparable conditions. Change one factor at a time—for example, index type, vector construction, query construction, rank function, or rank weights—so observed differences have a plausible cause. PostgreSQL does not prescribe a universal benchmark recipe or latency threshold; define acceptance against your service’s own SLO.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Evaluate relevance with judged queries and results
Create a fixed set of representative user queries and judge returned documents against the outcomes your application wants. The judgments might identify relevant results, grade degrees of relevance, or specify which documents should appear near the top; choose a consistent method and apply it across variants. This evaluation set is distinct from the load test: throughput and response time do not tell you whether the order is useful.
Compare rank functions and settings on that same set. ts_rank scores matching lexeme frequency; ts_rank_cd also considers proximity and needs positional information. Both support weights and normalization options. Try changes to field weights, document-length normalization, query construction, and, where the product needs it, application-specific factors such as freshness. Keep a change only if judged results improve for the intended outcome, while separately checking its performance cost. PostgreSQL 18: Controlling Text Search
Neither function produces a globally calibrated probability of relevance. Normalization option 32 maps scores to a 0–1 range but does not change result ordering. A score of 0.8 therefore does not mean an 80% chance that a result is relevant. Compare ordering and judgments, not the apparent probability implied by the numeric scale. PostgreSQL 18: Controlling Text Search
Recommended Free Tools
Turn the results into a production decision
- If the plan or buffer evidence shows an unexpected scan, recheck burden, or sort cost, investigate that path before attributing latency to concurrency alone.
- If latency or schedule lag worsens as concurrency or target rate rises, compare the observed capacity with your service’s own SLO and expected demand; there is no universal rate or latency target in PostgreSQL’s documentation.
- If a ranking change improves judged ordering but increases response time, decide whether the relevance gain justifies that cost for the product, then repeat both evaluations under the same conditions.
- If rankings change unexpectedly, verify the text-search configuration, vector construction, query parsing, and judgments before treating a score change as a relevance improvement.
A defensible production result is a measured account of the query mix, data, PostgreSQL version, environment, plan behavior, latency, throughput, lag, and judged ranking outcomes. It does not claim one index or ranking formula is best for every application.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




