mirror of
https://akkoma.dev/AkkomaGang/akkoma.git
synced 2024-11-17 18:49:15 +00:00
Raise minimum PostgreSQL version to 12
This lets us: - avoid issues with broken hash indices for PostgreSQL <10 - drop runtime checks and legacy codepaths for <11 in db search - always enable custom query plans for performance optimisation PostgreSQL 11 is already EOL since 2023-11-09, so in theory everyone should already have moved on to 12 anyway.
This commit is contained in:
parent
b17d3dc6d8
commit
a3840e7d1f
|
@ -6,6 +6,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
|
|
||||||
## UNRELEASED
|
## UNRELEASED
|
||||||
|
|
||||||
|
## BREAKING
|
||||||
|
- Minimum PostgreSQL version is raised to 12
|
||||||
|
|
||||||
## Added
|
## Added
|
||||||
- Implement [FEP-67ff](https://codeberg.org/fediverse/fep/src/branch/main/fep/67ff/fep-67ff.md) (federation documentation)
|
- Implement [FEP-67ff](https://codeberg.org/fediverse/fep/src/branch/main/fep/67ff/fep-67ff.md) (federation documentation)
|
||||||
- Meilisearch: it is now possible to use separate keys for search and admin actions
|
- Meilisearch: it is now possible to use separate keys for search and admin actions
|
||||||
|
|
|
@ -813,8 +813,10 @@
|
||||||
config :pleroma, configurable_from_database: false
|
config :pleroma, configurable_from_database: false
|
||||||
|
|
||||||
config :pleroma, Pleroma.Repo,
|
config :pleroma, Pleroma.Repo,
|
||||||
parameters: [gin_fuzzy_search_limit: "500"],
|
parameters: [
|
||||||
prepare: :unnamed
|
gin_fuzzy_search_limit: "500",
|
||||||
|
plan_cache_mode: "force_custom_plan"
|
||||||
|
]
|
||||||
|
|
||||||
config :pleroma, :majic_pool, size: 2
|
config :pleroma, :majic_pool, size: 2
|
||||||
|
|
||||||
|
|
|
@ -11,21 +11,3 @@ It is also recommended to not use "Network Storage" option.
|
||||||
If your server runs other services, you may want to take that into account. E.g. if you have 4G ram, but 1G of it is already used for other services, it may be better to tell PGTune you only have 3G.
|
If your server runs other services, you may want to take that into account. E.g. if you have 4G ram, but 1G of it is already used for other services, it may be better to tell PGTune you only have 3G.
|
||||||
|
|
||||||
In the end, PGTune only provides recomended settings, you can always try to finetune further.
|
In the end, PGTune only provides recomended settings, you can always try to finetune further.
|
||||||
|
|
||||||
## Disable generic query plans
|
|
||||||
|
|
||||||
When PostgreSQL receives a query, it decides on a strategy for searching the requested data, this is called a query plan. The query planner has two modes: generic and custom. Generic makes a plan for all queries of the same shape, ignoring the parameters, which is then cached and reused. Custom, on the contrary, generates a unique query plan based on query parameters.
|
|
||||||
|
|
||||||
By default PostgreSQL has an algorithm to decide which mode is more efficient for particular query, however this algorithm has been observed to be wrong on some of the queries Akkoma sends, leading to serious performance loss. Therefore, it is recommended to disable generic mode.
|
|
||||||
|
|
||||||
|
|
||||||
Akkoma already avoids generic query plans by default, however the method it uses is not the most efficient because it needs to be compatible with all supported PostgreSQL versions. For PostgreSQL 12 and higher additional performance can be gained by adding the following to Akkoma configuration:
|
|
||||||
```elixir
|
|
||||||
config :pleroma, Pleroma.Repo,
|
|
||||||
prepare: :named,
|
|
||||||
parameters: [
|
|
||||||
plan_cache_mode: "force_custom_plan"
|
|
||||||
]
|
|
||||||
```
|
|
||||||
|
|
||||||
A more detailed explaination of the issue can be found at <https://blog.soykaf.com/post/postgresql-elixir-troubles/>.
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
## Required dependencies
|
## Required dependencies
|
||||||
|
|
||||||
* PostgreSQL 9.6+
|
* PostgreSQL 12+
|
||||||
* Elixir 1.14+ (currently tested up to 1.16)
|
* Elixir 1.14+ (currently tested up to 1.16)
|
||||||
* Erlang OTP 25+ (currently tested up to OTP26)
|
* Erlang OTP 25+ (currently tested up to OTP26)
|
||||||
* git
|
* git
|
||||||
|
|
|
@ -95,10 +95,10 @@ def start(_type, _args) do
|
||||||
|
|
||||||
opts = [strategy: :one_for_one, name: Pleroma.Supervisor, max_restarts: max_restarts]
|
opts = [strategy: :one_for_one, name: Pleroma.Supervisor, max_restarts: max_restarts]
|
||||||
|
|
||||||
with {:ok, data} <- Supervisor.start_link(children, opts) do
|
case Supervisor.start_link(children, opts) do
|
||||||
set_postgres_server_version()
|
{:ok, data} ->
|
||||||
{:ok, data}
|
{:ok, data}
|
||||||
else
|
|
||||||
e ->
|
e ->
|
||||||
Logger.error("Failed to start!")
|
Logger.error("Failed to start!")
|
||||||
Logger.error("#{inspect(e)}")
|
Logger.error("#{inspect(e)}")
|
||||||
|
@ -106,23 +106,6 @@ def start(_type, _args) do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp set_postgres_server_version do
|
|
||||||
version =
|
|
||||||
with %{rows: [[version]]} <- Ecto.Adapters.SQL.query!(Pleroma.Repo, "show server_version"),
|
|
||||||
{num, _} <- Float.parse(version) do
|
|
||||||
num
|
|
||||||
else
|
|
||||||
e ->
|
|
||||||
Logger.warning(
|
|
||||||
"Could not get the postgres version: #{inspect(e)}.\nSetting the default value of 9.6"
|
|
||||||
)
|
|
||||||
|
|
||||||
9.6
|
|
||||||
end
|
|
||||||
|
|
||||||
:persistent_term.put({Pleroma.Repo, :postgres_version}, version)
|
|
||||||
end
|
|
||||||
|
|
||||||
def load_custom_modules do
|
def load_custom_modules do
|
||||||
dir = Config.get([:modules, :runtime_dir])
|
dir = Config.get([:modules, :runtime_dir])
|
||||||
|
|
||||||
|
|
|
@ -21,19 +21,12 @@ def search(user, search_query, options \\ []) do
|
||||||
offset = Keyword.get(options, :offset, 0)
|
offset = Keyword.get(options, :offset, 0)
|
||||||
author = Keyword.get(options, :author)
|
author = Keyword.get(options, :author)
|
||||||
|
|
||||||
search_function =
|
|
||||||
if :persistent_term.get({Pleroma.Repo, :postgres_version}) >= 11 do
|
|
||||||
:websearch
|
|
||||||
else
|
|
||||||
:plain
|
|
||||||
end
|
|
||||||
|
|
||||||
try do
|
try do
|
||||||
Activity
|
Activity
|
||||||
|> Activity.with_preloaded_object()
|
|> Activity.with_preloaded_object()
|
||||||
|> Activity.restrict_deactivated_users()
|
|> Activity.restrict_deactivated_users()
|
||||||
|> restrict_public()
|
|> restrict_public()
|
||||||
|> query_with(index_type, search_query, search_function)
|
|> query_with(index_type, search_query)
|
||||||
|> maybe_restrict_local(user)
|
|> maybe_restrict_local(user)
|
||||||
|> maybe_restrict_author(author)
|
|> maybe_restrict_author(author)
|
||||||
|> maybe_restrict_blocked(user)
|
|> maybe_restrict_blocked(user)
|
||||||
|
@ -72,25 +65,7 @@ def restrict_public(q) do
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
defp query_with(q, :gin, search_query, :plain) do
|
defp query_with(q, :gin, search_query) do
|
||||||
%{rows: [[tsc]]} =
|
|
||||||
Ecto.Adapters.SQL.query!(
|
|
||||||
Pleroma.Repo,
|
|
||||||
"select current_setting('default_text_search_config')::regconfig::oid;"
|
|
||||||
)
|
|
||||||
|
|
||||||
from([a, o] in q,
|
|
||||||
where:
|
|
||||||
fragment(
|
|
||||||
"to_tsvector(?::oid::regconfig, ?->>'content') @@ plainto_tsquery(?)",
|
|
||||||
^tsc,
|
|
||||||
o.data,
|
|
||||||
^search_query
|
|
||||||
)
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp query_with(q, :gin, search_query, :websearch) do
|
|
||||||
%{rows: [[tsc]]} =
|
%{rows: [[tsc]]} =
|
||||||
Ecto.Adapters.SQL.query!(
|
Ecto.Adapters.SQL.query!(
|
||||||
Pleroma.Repo,
|
Pleroma.Repo,
|
||||||
|
@ -108,19 +83,7 @@ defp query_with(q, :gin, search_query, :websearch) do
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
defp query_with(q, :rum, search_query, :plain) do
|
defp query_with(q, :rum, search_query) do
|
||||||
from([a, o] in q,
|
|
||||||
where:
|
|
||||||
fragment(
|
|
||||||
"? @@ plainto_tsquery(?)",
|
|
||||||
o.fts_content,
|
|
||||||
^search_query
|
|
||||||
),
|
|
||||||
order_by: [fragment("? <=> now()::date", o.inserted_at)]
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp query_with(q, :rum, search_query, :websearch) do
|
|
||||||
from([a, o] in q,
|
from([a, o] in q,
|
||||||
where:
|
where:
|
||||||
fragment(
|
fragment(
|
||||||
|
|
|
@ -18,21 +18,6 @@ test "it finds something" do
|
||||||
assert result.id == post.id
|
assert result.id == post.id
|
||||||
end
|
end
|
||||||
|
|
||||||
test "using plainto_tsquery on postgres < 11" do
|
|
||||||
old_version = :persistent_term.get({Pleroma.Repo, :postgres_version})
|
|
||||||
:persistent_term.put({Pleroma.Repo, :postgres_version}, 10.0)
|
|
||||||
on_exit(fn -> :persistent_term.put({Pleroma.Repo, :postgres_version}, old_version) end)
|
|
||||||
|
|
||||||
user = insert(:user)
|
|
||||||
{:ok, post} = CommonAPI.post(user, %{status: "it's wednesday my dudes"})
|
|
||||||
{:ok, _post2} = CommonAPI.post(user, %{status: "it's wednesday my bros"})
|
|
||||||
|
|
||||||
# plainto doesn't understand complex queries
|
|
||||||
assert [result] = DatabaseSearch.search(nil, "wednesday -dudes")
|
|
||||||
|
|
||||||
assert result.id == post.id
|
|
||||||
end
|
|
||||||
|
|
||||||
test "using websearch_to_tsquery" do
|
test "using websearch_to_tsquery" do
|
||||||
user = insert(:user)
|
user = insert(:user)
|
||||||
{:ok, _post} = CommonAPI.post(user, %{status: "it's wednesday my dudes"})
|
{:ok, _post} = CommonAPI.post(user, %{status: "it's wednesday my dudes"})
|
||||||
|
|
Loading…
Reference in a new issue