├── .github └── workflows │ └── build.yaml ├── .gitignore ├── LICENSE ├── README.md ├── postgresql.example.conf └── src ├── build.spec └── main.py /.github/workflows/build.yaml: -------------------------------------------------------------------------------- 1 | name: Build & release 2 | on: 3 | push: 4 | tags: [v**] 5 | permissions: 6 | contents: write 7 | jobs: 8 | build: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: Checkout 12 | uses: actions/checkout@v4 13 | - name: Package Application 14 | uses: JackMcKew/pyinstaller-action-windows@main 15 | with: 16 | path: src 17 | - name: Release 18 | uses: softprops/action-gh-release@v2 19 | with: 20 | files: src/dist/windows/1cv8_postgres_helper.exe 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | share/python-wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | MANIFEST 28 | 29 | # PyInstaller 30 | # Usually these files are written by a python script from a template 31 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 32 | *.manifest 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .nox/ 42 | .coverage 43 | .coverage.* 44 | .cache 45 | nosetests.xml 46 | coverage.xml 47 | *.cover 48 | *.py,cover 49 | .hypothesis/ 50 | .pytest_cache/ 51 | cover/ 52 | 53 | # Translations 54 | *.mo 55 | *.pot 56 | 57 | # Django stuff: 58 | *.log 59 | local_settings.py 60 | db.sqlite3 61 | db.sqlite3-journal 62 | 63 | # Flask stuff: 64 | instance/ 65 | .webassets-cache 66 | 67 | # Scrapy stuff: 68 | .scrapy 69 | 70 | # Sphinx documentation 71 | docs/_build/ 72 | 73 | # PyBuilder 74 | .pybuilder/ 75 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | 80 | # IPython 81 | profile_default/ 82 | ipython_config.py 83 | 84 | # pyenv 85 | # For a library or package, you might want to ignore these files since the code is 86 | # intended to run in multiple environments; otherwise, check them in: 87 | # .python-version 88 | 89 | # pipenv 90 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 91 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 92 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 93 | # install all needed dependencies. 94 | #Pipfile.lock 95 | 96 | # poetry 97 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. 98 | # This is especially recommended for binary packages to ensure reproducibility, and is more 99 | # commonly ignored for libraries. 100 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control 101 | #poetry.lock 102 | 103 | # pdm 104 | # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. 105 | #pdm.lock 106 | # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it 107 | # in version control. 108 | # https://pdm.fming.dev/#use-with-ide 109 | .pdm.toml 110 | 111 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm 112 | __pypackages__/ 113 | 114 | # Celery stuff 115 | celerybeat-schedule 116 | celerybeat.pid 117 | 118 | # SageMath parsed files 119 | *.sage.py 120 | 121 | # Environments 122 | .env 123 | .venv 124 | env/ 125 | venv/ 126 | ENV/ 127 | env.bak/ 128 | venv.bak/ 129 | 130 | # Spyder project settings 131 | .spyderproject 132 | .spyproject 133 | 134 | # Rope project settings 135 | .ropeproject 136 | 137 | # mkdocs documentation 138 | /site 139 | 140 | # mypy 141 | .mypy_cache/ 142 | .dmypy.json 143 | dmypy.json 144 | 145 | # Pyre type checker 146 | .pyre/ 147 | 148 | # pytype static type analyzer 149 | .pytype/ 150 | 151 | # Cython debug symbols 152 | cython_debug/ 153 | 154 | # PyCharm 155 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can 156 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore 157 | # and can be added to the global gitignore or merged into this file. For a more nuclear 158 | # option (not recommended) you can uncomment the following to ignore the entire idea folder. 159 | #.idea/ 160 | 161 | # VSCode 162 | .vscode 163 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Ilya Bogdanov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Postgresql config helper для 1С Предприятие 2 | Скрипт, изменяющий конфигурацию PostgreSQL согласно [рекомендациями из документации 1С](https://its.1c.ru/db/metod8dev#content:5866:hdoc) 3 | 4 | # Использование 5 | 6 | ## Показать встроенную справку 7 | 8 | ```powershell 9 | 1cv8_postgres_helper.exe --help 10 | ``` 11 | 12 | ## Наиболее простой вариант 13 | 14 | ```powershell 15 | 1cv8_postgres_helper.exe --config postgresql.example.conf --mem 32GB 16 | ``` 17 | 18 | ## Все доступные аргументы 19 | 20 | ```powershell 21 | 1cv8_postgres_helper.exe --config postgresql.example.conf --mem 32GB --cpu 8 --storage ssd --disable-synchronous-commit --enable-group-commit --no-backup 22 | ``` 23 | -------------------------------------------------------------------------------- /postgresql.example.conf: -------------------------------------------------------------------------------- 1 | # ----------------------------- 2 | # PostgreSQL configuration file 3 | # ----------------------------- 4 | # 5 | # This file consists of lines of the form: 6 | # 7 | # name = value 8 | # 9 | # (The "=" is optional.) Whitespace may be used. Comments are introduced with 10 | # "#" anywhere on a line. The complete list of parameter names and allowed 11 | # values can be found in the PostgreSQL documentation. 12 | # 13 | # The commented-out settings shown in this file represent the default values. 14 | # Re-commenting a setting is NOT sufficient to revert it to the default value; 15 | # you need to reload the server. 16 | # 17 | # This file is read on server startup and when the server receives a SIGHUP 18 | # signal. If you edit the file on a running system, you have to SIGHUP the 19 | # server for the changes to take effect, run "pg_ctl reload", or execute 20 | # "SELECT pg_reload_conf()". Some parameters, which are marked below, 21 | # require a server shutdown and restart to take effect. 22 | # 23 | # Any parameter can also be given as a command-line option to the server, e.g., 24 | # "postgres -c log_connections=on". Some parameters can be changed at run time 25 | # with the "SET" SQL command. 26 | # 27 | # Memory units: B = bytes Time units: us = microseconds 28 | # kB = kilobytes ms = milliseconds 29 | # MB = megabytes s = seconds 30 | # GB = gigabytes min = minutes 31 | # TB = terabytes h = hours 32 | # d = days 33 | 34 | 35 | #------------------------------------------------------------------------------ 36 | # FILE LOCATIONS 37 | #------------------------------------------------------------------------------ 38 | 39 | # The default values of these variables are driven from the -D command-line 40 | # option or PGDATA environment variable, represented here as ConfigDir. 41 | 42 | #data_directory = 'ConfigDir' # use data in another directory 43 | # (change requires restart) 44 | #hba_file = 'ConfigDir/pg_hba.conf' # host-based authentication file 45 | # (change requires restart) 46 | #ident_file = 'ConfigDir/pg_ident.conf' # ident configuration file 47 | # (change requires restart) 48 | 49 | # If external_pid_file is not explicitly set, no extra PID file is written. 50 | #external_pid_file = '' # write an extra PID file 51 | # (change requires restart) 52 | 53 | 54 | #------------------------------------------------------------------------------ 55 | # CONNECTIONS AND AUTHENTICATION 56 | #------------------------------------------------------------------------------ 57 | 58 | # - Connection Settings - 59 | 60 | listen_addresses = '*' # what IP address(es) to listen on; 61 | # comma-separated list of addresses; 62 | # defaults to 'localhost'; use '*' for all 63 | # (change requires restart) 64 | port = 5432 # (change requires restart) 65 | max_connections = 100 # (change requires restart) 66 | #superuser_reserved_connections = 3 # (change requires restart) 67 | #unix_socket_directories = '' # comma-separated list of directories 68 | # (change requires restart) 69 | #unix_socket_group = '' # (change requires restart) 70 | #unix_socket_permissions = 0777 # begin with 0 to use octal notation 71 | # (change requires restart) 72 | #bonjour = off # advertise server via Bonjour 73 | # (change requires restart) 74 | #bonjour_name = '' # defaults to the computer name 75 | # (change requires restart) 76 | 77 | # - TCP settings - 78 | # see "man tcp" for details 79 | 80 | #tcp_keepalives_idle = 0 # TCP_KEEPIDLE, in seconds; 81 | # 0 selects the system default 82 | #tcp_keepalives_interval = 0 # TCP_KEEPINTVL, in seconds; 83 | # 0 selects the system default 84 | #tcp_keepalives_count = 0 # TCP_KEEPCNT; 85 | # 0 selects the system default 86 | #tcp_user_timeout = 0 # TCP_USER_TIMEOUT, in milliseconds; 87 | # 0 selects the system default 88 | 89 | #client_connection_check_interval = 0 # time between checks for client 90 | # disconnection while running queries; 91 | # 0 for never 92 | 93 | # - Authentication - 94 | 95 | #authentication_timeout = 1min # 1s-600s 96 | password_encryption = md5 # scram-sha-256 or md5 97 | #db_user_namespace = off 98 | 99 | # GSSAPI using Kerberos 100 | #krb_server_keyfile = 'FILE:${sysconfdir}/krb5.keytab' 101 | #krb_caseins_users = off 102 | 103 | # - SSL - 104 | 105 | #ssl = off 106 | #ssl_ca_file = '' 107 | #ssl_cert_file = 'server.crt' 108 | #ssl_crl_file = '' 109 | #ssl_crl_dir = '' 110 | #ssl_key_file = 'server.key' 111 | #ssl_ciphers = 'HIGH:MEDIUM:+3DES:!aNULL' # allowed SSL ciphers 112 | #ssl_prefer_server_ciphers = on 113 | #ssl_ecdh_curve = 'prime256v1' 114 | #ssl_min_protocol_version = 'TLSv1.2' 115 | #ssl_max_protocol_version = '' 116 | #ssl_dh_params_file = '' 117 | #ssl_passphrase_command = '' 118 | #ssl_passphrase_command_supports_reload = off 119 | 120 | 121 | #------------------------------------------------------------------------------ 122 | # RESOURCE USAGE (except WAL) 123 | #------------------------------------------------------------------------------ 124 | 125 | # - Memory - 126 | 127 | shared_buffers = 128MB # min 128kB 128 | # (change requires restart) 129 | #huge_pages = try # on, off, or try 130 | # (change requires restart) 131 | #huge_page_size = 0 # zero for system default 132 | # (change requires restart) 133 | #temp_buffers = 8MB # min 800kB 134 | #max_prepared_transactions = 0 # zero disables the feature 135 | # (change requires restart) 136 | # Caution: it is not advisable to set max_prepared_transactions nonzero unless 137 | # you actively intend to use prepared transactions. 138 | #work_mem = 4MB # min 64kB 139 | #hash_mem_multiplier = 2.0 # 1-1000.0 multiplier on hash table work_mem 140 | #maintenance_work_mem = 64MB # min 1MB 141 | #autovacuum_work_mem = -1 # min 1MB, or -1 to use maintenance_work_mem 142 | #logical_decoding_work_mem = 64MB # min 64kB 143 | #max_stack_depth = 2MB # min 100kB 144 | #shared_memory_type = mmap # the default is the first option 145 | # supported by the operating system: 146 | # mmap 147 | # sysv 148 | # windows 149 | # (change requires restart) 150 | dynamic_shared_memory_type = windows # the default is usually the first option 151 | # supported by the operating system: 152 | # posix 153 | # sysv 154 | # windows 155 | # mmap 156 | # (change requires restart) 157 | #min_dynamic_shared_memory = 0MB # (change requires restart) 158 | 159 | # - Disk - 160 | 161 | #temp_file_limit = -1 # limits per-process temp file space 162 | # in kilobytes, or -1 for no limit 163 | 164 | # - Kernel Resources - 165 | 166 | #max_files_per_process = 1000 # min 64 167 | # (change requires restart) 168 | 169 | # - Cost-Based Vacuum Delay - 170 | 171 | #vacuum_cost_delay = 0 # 0-100 milliseconds (0 disables) 172 | #vacuum_cost_page_hit = 1 # 0-10000 credits 173 | #vacuum_cost_page_miss = 2 # 0-10000 credits 174 | #vacuum_cost_page_dirty = 20 # 0-10000 credits 175 | #vacuum_cost_limit = 200 # 1-10000 credits 176 | 177 | # - Background Writer - 178 | 179 | #bgwriter_delay = 200ms # 10-10000ms between rounds 180 | #bgwriter_lru_maxpages = 100 # max buffers written/round, 0 disables 181 | #bgwriter_lru_multiplier = 2.0 # 0-10.0 multiplier on buffers scanned/round 182 | #bgwriter_flush_after = 0 # measured in pages, 0 disables 183 | 184 | # - Asynchronous Behavior - 185 | 186 | #backend_flush_after = 0 # measured in pages, 0 disables 187 | #effective_io_concurrency = 0 # 1-1000; 0 disables prefetching 188 | #maintenance_io_concurrency = 10 # 1-1000; 0 disables prefetching 189 | #max_worker_processes = 8 # (change requires restart) 190 | #max_parallel_workers_per_gather = 2 # taken from max_parallel_workers 191 | #max_parallel_maintenance_workers = 2 # taken from max_parallel_workers 192 | #max_parallel_workers = 8 # maximum number of max_worker_processes that 193 | # can be used in parallel operations 194 | #parallel_leader_participation = on 195 | #old_snapshot_threshold = -1 # 1min-60d; -1 disables; 0 is immediate 196 | # (change requires restart) 197 | 198 | 199 | #------------------------------------------------------------------------------ 200 | # WRITE-AHEAD LOG 201 | #------------------------------------------------------------------------------ 202 | 203 | # - Settings - 204 | 205 | #wal_level = replica # minimal, replica, or logical 206 | # (change requires restart) 207 | #fsync = on # flush data to disk for crash safety 208 | # (turning this off can cause 209 | # unrecoverable data corruption) 210 | #synchronous_commit = on # synchronization level; 211 | # off, local, remote_write, remote_apply, or on 212 | #wal_sync_method = fsync # the default is the first option 213 | # supported by the operating system: 214 | # open_datasync 215 | # fdatasync (default on Linux and FreeBSD) 216 | # fsync 217 | # fsync_writethrough 218 | # open_sync 219 | #full_page_writes = on # recover from partial page writes 220 | #wal_log_hints = off # also do full page writes of non-critical updates 221 | # (change requires restart) 222 | #wal_compression = off # enables compression of full-page writes; 223 | # off, pglz, lz4, zstd, or on 224 | #wal_init_zero = on # zero-fill new WAL files 225 | #wal_recycle = on # recycle WAL files 226 | #wal_buffers = -1 # min 32kB, -1 sets based on shared_buffers 227 | # (change requires restart) 228 | #wal_writer_delay = 200ms # 1-10000 milliseconds 229 | #wal_writer_flush_after = 1MB # measured in pages, 0 disables 230 | #wal_skip_threshold = 2MB 231 | 232 | #commit_delay = 0 # range 0-100000, in microseconds 233 | #commit_siblings = 5 # range 1-1000 234 | 235 | # - Checkpoints - 236 | 237 | #checkpoint_timeout = 5min # range 30s-1d 238 | #checkpoint_completion_target = 0.9 # checkpoint target duration, 0.0 - 1.0 239 | #checkpoint_flush_after = 0 # measured in pages, 0 disables 240 | #checkpoint_warning = 30s # 0 disables 241 | max_wal_size = 1GB 242 | min_wal_size = 80MB 243 | 244 | # - Prefetching during recovery - 245 | 246 | #recovery_prefetch = try # prefetch pages referenced in the WAL? 247 | #wal_decode_buffer_size = 512kB # lookahead window used for prefetching 248 | # (change requires restart) 249 | 250 | # - Archiving - 251 | 252 | #archive_mode = off # enables archiving; off, on, or always 253 | # (change requires restart) 254 | #archive_library = '' # library to use to archive a logfile segment 255 | # (empty string indicates archive_command should 256 | # be used) 257 | #archive_command = '' # command to use to archive a logfile segment 258 | # placeholders: %p = path of file to archive 259 | # %f = file name only 260 | # e.g. 'test ! -f /mnt/server/archivedir/%f && cp %p /mnt/server/archivedir/%f' 261 | #archive_timeout = 0 # force a logfile segment switch after this 262 | # number of seconds; 0 disables 263 | 264 | # - Archive Recovery - 265 | 266 | # These are only used in recovery mode. 267 | 268 | #restore_command = '' # command to use to restore an archived logfile segment 269 | # placeholders: %p = path of file to restore 270 | # %f = file name only 271 | # e.g. 'cp /mnt/server/archivedir/%f %p' 272 | #archive_cleanup_command = '' # command to execute at every restartpoint 273 | #recovery_end_command = '' # command to execute at completion of recovery 274 | 275 | # - Recovery Target - 276 | 277 | # Set these only when performing a targeted recovery. 278 | 279 | #recovery_target = '' # 'immediate' to end recovery as soon as a 280 | # consistent state is reached 281 | # (change requires restart) 282 | #recovery_target_name = '' # the named restore point to which recovery will proceed 283 | # (change requires restart) 284 | #recovery_target_time = '' # the time stamp up to which recovery will proceed 285 | # (change requires restart) 286 | #recovery_target_xid = '' # the transaction ID up to which recovery will proceed 287 | # (change requires restart) 288 | #recovery_target_lsn = '' # the WAL LSN up to which recovery will proceed 289 | # (change requires restart) 290 | #recovery_target_inclusive = on # Specifies whether to stop: 291 | # just after the specified recovery target (on) 292 | # just before the recovery target (off) 293 | # (change requires restart) 294 | #recovery_target_timeline = 'latest' # 'current', 'latest', or timeline ID 295 | # (change requires restart) 296 | #recovery_target_action = 'pause' # 'pause', 'promote', 'shutdown' 297 | # (change requires restart) 298 | 299 | 300 | #------------------------------------------------------------------------------ 301 | # REPLICATION 302 | #------------------------------------------------------------------------------ 303 | 304 | # - Sending Servers - 305 | 306 | # Set these on the primary and on any standby that will send replication data. 307 | 308 | #max_wal_senders = 10 # max number of walsender processes 309 | # (change requires restart) 310 | #max_replication_slots = 10 # max number of replication slots 311 | # (change requires restart) 312 | #wal_keep_size = 0 # in megabytes; 0 disables 313 | #max_slot_wal_keep_size = -1 # in megabytes; -1 disables 314 | #wal_sender_timeout = 60s # in milliseconds; 0 disables 315 | #track_commit_timestamp = off # collect timestamp of transaction commit 316 | # (change requires restart) 317 | 318 | # - Primary Server - 319 | 320 | # These settings are ignored on a standby server. 321 | 322 | #synchronous_standby_names = '' # standby servers that provide sync rep 323 | # method to choose sync standbys, number of sync standbys, 324 | # and comma-separated list of application_name 325 | # from standby(s); '*' = all 326 | #vacuum_defer_cleanup_age = 0 # number of xacts by which cleanup is delayed 327 | 328 | # - Standby Servers - 329 | 330 | # These settings are ignored on a primary server. 331 | 332 | #primary_conninfo = '' # connection string to sending server 333 | #primary_slot_name = '' # replication slot on sending server 334 | #promote_trigger_file = '' # file name whose presence ends recovery 335 | #hot_standby = on # "off" disallows queries during recovery 336 | # (change requires restart) 337 | #max_standby_archive_delay = 30s # max delay before canceling queries 338 | # when reading WAL from archive; 339 | # -1 allows indefinite delay 340 | #max_standby_streaming_delay = 30s # max delay before canceling queries 341 | # when reading streaming WAL; 342 | # -1 allows indefinite delay 343 | #wal_receiver_create_temp_slot = off # create temp slot if primary_slot_name 344 | # is not set 345 | #wal_receiver_status_interval = 10s # send replies at least this often 346 | # 0 disables 347 | #hot_standby_feedback = off # send info from standby to prevent 348 | # query conflicts 349 | #wal_receiver_timeout = 60s # time that receiver waits for 350 | # communication from primary 351 | # in milliseconds; 0 disables 352 | #wal_retrieve_retry_interval = 5s # time to wait before retrying to 353 | # retrieve WAL after a failed attempt 354 | #recovery_min_apply_delay = 0 # minimum delay for applying changes during recovery 355 | 356 | # - Subscribers - 357 | 358 | # These settings are ignored on a publisher. 359 | 360 | #max_logical_replication_workers = 4 # taken from max_worker_processes 361 | # (change requires restart) 362 | #max_sync_workers_per_subscription = 2 # taken from max_logical_replication_workers 363 | 364 | 365 | #------------------------------------------------------------------------------ 366 | # QUERY TUNING 367 | #------------------------------------------------------------------------------ 368 | 369 | # - Planner Method Configuration - 370 | 371 | #enable_async_append = on 372 | #enable_bitmapscan = on 373 | #enable_gathermerge = on 374 | #enable_hashagg = on 375 | #enable_hashjoin = on 376 | #enable_incremental_sort = on 377 | #enable_indexscan = on 378 | #enable_indexonlyscan = on 379 | #enable_material = on 380 | #enable_memoize = on 381 | #enable_mergejoin = on 382 | #enable_nestloop = on 383 | #enable_parallel_append = on 384 | #enable_parallel_hash = on 385 | #enable_partition_pruning = on 386 | #enable_partitionwise_join = off 387 | #enable_partitionwise_aggregate = off 388 | #enable_seqscan = on 389 | #enable_sort = on 390 | #enable_tidscan = on 391 | #enable_group_by_reordering = on 392 | 393 | # - Planner Cost Constants - 394 | 395 | #seq_page_cost = 1.0 # measured on an arbitrary scale 396 | #random_page_cost = 4.0 # same scale as above 397 | #cpu_tuple_cost = 0.01 # same scale as above 398 | #cpu_index_tuple_cost = 0.005 # same scale as above 399 | #cpu_operator_cost = 0.0025 # same scale as above 400 | #parallel_setup_cost = 1000.0 # same scale as above 401 | #parallel_tuple_cost = 0.1 # same scale as above 402 | #min_parallel_table_scan_size = 8MB 403 | #min_parallel_index_scan_size = 512kB 404 | #effective_cache_size = 4GB 405 | 406 | #jit_above_cost = 100000 # perform JIT compilation if available 407 | # and query more expensive than this; 408 | # -1 disables 409 | #jit_inline_above_cost = 500000 # inline small functions if query is 410 | # more expensive than this; -1 disables 411 | #jit_optimize_above_cost = 500000 # use expensive JIT optimizations if 412 | # query is more expensive than this; 413 | # -1 disables 414 | 415 | # - Genetic Query Optimizer - 416 | 417 | #geqo = on 418 | #geqo_threshold = 12 419 | #geqo_effort = 5 # range 1-10 420 | #geqo_pool_size = 0 # selects default based on effort 421 | #geqo_generations = 0 # selects default based on effort 422 | #geqo_selection_bias = 2.0 # range 1.5-2.0 423 | #geqo_seed = 0.0 # range 0.0-1.0 424 | 425 | # - Other Planner Options - 426 | 427 | #default_statistics_target = 100 # range 1-10000 428 | #constraint_exclusion = partition # on, off, or partition 429 | #cursor_tuple_fraction = 0.1 # range 0.0-1.0 430 | #from_collapse_limit = 8 431 | #jit = on # allow JIT compilation 432 | #join_collapse_limit = 8 # 1 disables collapsing of explicit 433 | # JOIN clauses 434 | #plan_cache_mode = auto # auto, force_generic_plan or 435 | # force_custom_plan 436 | #recursive_worktable_factor = 10.0 # range 0.001-1000000 437 | 438 | 439 | #------------------------------------------------------------------------------ 440 | # REPORTING AND LOGGING 441 | #------------------------------------------------------------------------------ 442 | 443 | # - Where to Log - 444 | 445 | log_destination = 'stderr' # Valid values are combinations of 446 | # stderr, csvlog, jsonlog, syslog, and 447 | # eventlog, depending on platform. 448 | # csvlog and jsonlog require 449 | # logging_collector to be on. 450 | 451 | # This is used when logging to stderr: 452 | logging_collector = on # Enable capturing of stderr, jsonlog, 453 | # and csvlog into log files. Required 454 | # to be on for csvlogs and jsonlogs. 455 | # (change requires restart) 456 | 457 | # These are only used if logging_collector is on: 458 | #log_directory = 'log' # directory where log files are written, 459 | # can be absolute or relative to PGDATA 460 | #log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log' # log file name pattern, 461 | # can include strftime() escapes 462 | log_file_mode = 0640 # creation mode for log files, 463 | # begin with 0 to use octal notation 464 | #log_rotation_age = 1d # Automatic rotation of logfiles will 465 | # happen after that time. 0 disables. 466 | #log_rotation_size = 10MB # Automatic rotation of logfiles will 467 | # happen after that much log output. 468 | # 0 disables. 469 | #log_truncate_on_rotation = off # If on, an existing log file with the 470 | # same name as the new log file will be 471 | # truncated rather than appended to. 472 | # But such truncation only occurs on 473 | # time-driven rotation, not on restarts 474 | # or size-driven rotation. Default is 475 | # off, meaning append to existing files 476 | # in all cases. 477 | 478 | # These are relevant when logging to syslog: 479 | #syslog_facility = 'LOCAL0' 480 | #syslog_ident = 'postgres' 481 | #syslog_sequence_numbers = on 482 | #syslog_split_messages = on 483 | 484 | # This is only relevant when logging to eventlog (Windows): 485 | # (change requires restart) 486 | #event_source = 'PostgreSQL' 487 | 488 | # - When to Log - 489 | 490 | #log_min_messages = warning # values in order of decreasing detail: 491 | # debug5 492 | # debug4 493 | # debug3 494 | # debug2 495 | # debug1 496 | # info 497 | # notice 498 | # warning 499 | # error 500 | # log 501 | # fatal 502 | # panic 503 | 504 | #log_min_error_statement = error # values in order of decreasing detail: 505 | # debug5 506 | # debug4 507 | # debug3 508 | # debug2 509 | # debug1 510 | # info 511 | # notice 512 | # warning 513 | # error 514 | # log 515 | # fatal 516 | # panic (effectively off) 517 | 518 | #log_min_duration_statement = -1 # -1 is disabled, 0 logs all statements 519 | # and their durations, > 0 logs only 520 | # statements running at least this number 521 | # of milliseconds 522 | 523 | #log_min_duration_sample = -1 # -1 is disabled, 0 logs a sample of statements 524 | # and their durations, > 0 logs only a sample of 525 | # statements running at least this number 526 | # of milliseconds; 527 | # sample fraction is determined by log_statement_sample_rate 528 | 529 | #log_statement_sample_rate = 1.0 # fraction of logged statements exceeding 530 | # log_min_duration_sample to be logged; 531 | # 1.0 logs all such statements, 0.0 never logs 532 | 533 | 534 | #log_transaction_sample_rate = 0.0 # fraction of transactions whose statements 535 | # are logged regardless of their duration; 1.0 logs all 536 | # statements from all transactions, 0.0 never logs 537 | 538 | #log_startup_progress_interval = 10s # Time between progress updates for 539 | # long-running startup operations. 540 | # 0 disables the feature, > 0 indicates 541 | # the interval in milliseconds. 542 | 543 | # - What to Log - 544 | 545 | #debug_print_parse = off 546 | #debug_print_rewritten = off 547 | #debug_print_plan = off 548 | #debug_pretty_print = on 549 | #log_autovacuum_min_duration = 10min # log autovacuum activity; 550 | # -1 disables, 0 logs all actions and 551 | # their durations, > 0 logs only 552 | # actions running at least this number 553 | # of milliseconds. 554 | #log_checkpoints = on 555 | #log_connections = off 556 | #log_disconnections = off 557 | #log_duration = off 558 | #log_error_verbosity = default # terse, default, or verbose messages 559 | #log_hostname = off 560 | #log_line_prefix = '%m [%p] ' # special values: 561 | # %a = application name 562 | # %u = user name 563 | # %d = database name 564 | # %r = remote host and port 565 | # %h = remote host 566 | # %b = backend type 567 | # %p = process ID 568 | # %P = process ID of parallel group leader 569 | # %t = timestamp without milliseconds 570 | # %m = timestamp with milliseconds 571 | # %n = timestamp with milliseconds (as a Unix epoch) 572 | # %Q = query ID (0 if none or not computed) 573 | # %i = command tag 574 | # %e = SQL state 575 | # %c = session ID 576 | # %l = session line number 577 | # %s = session start timestamp 578 | # %v = virtual transaction ID 579 | # %x = transaction ID (0 if none) 580 | # %q = stop here in non-session 581 | # processes 582 | # %% = '%' 583 | # e.g. '<%u%%%d> ' 584 | #log_lock_waits = off # log lock waits >= deadlock_timeout 585 | #log_recovery_conflict_waits = off # log standby recovery conflict waits 586 | # >= deadlock_timeout 587 | #log_parameter_max_length = -1 # when logging statements, limit logged 588 | # bind-parameter values to N bytes; 589 | # -1 means print in full, 0 disables 590 | #log_parameter_max_length_on_error = 0 # when logging an error, limit logged 591 | # bind-parameter values to N bytes; 592 | # -1 means print in full, 0 disables 593 | #log_statement = 'none' # none, ddl, mod, all 594 | #log_replication_commands = off 595 | #log_temp_files = -1 # log temporary files equal or larger 596 | # than the specified size in kilobytes; 597 | # -1 disables, 0 logs all temp files 598 | log_timezone = 'Europe/Moscow' 599 | 600 | 601 | #------------------------------------------------------------------------------ 602 | # PROCESS TITLE 603 | #------------------------------------------------------------------------------ 604 | 605 | #cluster_name = '' # added to process titles if nonempty 606 | # (change requires restart) 607 | #update_process_title = off 608 | 609 | 610 | #------------------------------------------------------------------------------ 611 | # STATISTICS 612 | #------------------------------------------------------------------------------ 613 | 614 | # - Cumulative Query and Index Statistics - 615 | 616 | #track_activities = on 617 | #track_activity_query_size = 1024 # (change requires restart) 618 | #track_counts = on 619 | #track_io_timing = off 620 | #track_wal_io_timing = off 621 | #track_functions = none # none, pl, all 622 | #stats_fetch_consistency = cache 623 | 624 | 625 | # - Monitoring - 626 | 627 | #compute_query_id = auto 628 | #log_statement_stats = off 629 | #log_parser_stats = off 630 | #log_planner_stats = off 631 | #log_executor_stats = off 632 | 633 | 634 | #------------------------------------------------------------------------------ 635 | # AUTOVACUUM 636 | #------------------------------------------------------------------------------ 637 | 638 | #autovacuum = on # Enable autovacuum subprocess? 'on' 639 | # requires track_counts to also be on. 640 | #autovacuum_max_workers = 3 # max number of autovacuum subprocesses 641 | # (change requires restart) 642 | #autovacuum_naptime = 1min # time between autovacuum runs 643 | #autovacuum_vacuum_threshold = 50 # min number of row updates before 644 | # vacuum 645 | #autovacuum_vacuum_insert_threshold = 1000 # min number of row inserts 646 | # before vacuum; -1 disables insert 647 | # vacuums 648 | #autovacuum_analyze_threshold = 50 # min number of row updates before 649 | # analyze 650 | #autovacuum_vacuum_scale_factor = 0.2 # fraction of table size before vacuum 651 | #autovacuum_vacuum_insert_scale_factor = 0.2 # fraction of inserts over table 652 | # size before insert vacuum 653 | #autovacuum_analyze_scale_factor = 0.1 # fraction of table size before analyze 654 | #autovacuum_freeze_max_age = 200000000 # maximum XID age before forced vacuum 655 | # (change requires restart) 656 | #autovacuum_multixact_freeze_max_age = 400000000 # maximum multixact age 657 | # before forced vacuum 658 | # (change requires restart) 659 | #autovacuum_vacuum_cost_delay = 2ms # default vacuum cost delay for 660 | # autovacuum, in milliseconds; 661 | # -1 means use vacuum_cost_delay 662 | #autovacuum_vacuum_cost_limit = -1 # default vacuum cost limit for 663 | # autovacuum, -1 means use 664 | # vacuum_cost_limit 665 | 666 | 667 | #------------------------------------------------------------------------------ 668 | # CLIENT CONNECTION DEFAULTS 669 | #------------------------------------------------------------------------------ 670 | 671 | # - Statement Behavior - 672 | 673 | #client_min_messages = notice # values in order of decreasing detail: 674 | # debug5 675 | # debug4 676 | # debug3 677 | # debug2 678 | # debug1 679 | # log 680 | # notice 681 | # warning 682 | # error 683 | #search_path = '"$user", public' # schema names 684 | #row_security = on 685 | #default_table_access_method = 'heap' 686 | #default_tablespace = '' # a tablespace name, '' uses the default 687 | #default_toast_compression = 'pglz' # 'pglz' or 'lz4' 688 | #temp_tablespaces = '' # a list of tablespace names, '' uses 689 | # only default tablespace 690 | #check_function_bodies = on 691 | #default_transaction_isolation = 'read committed' 692 | #default_transaction_read_only = off 693 | #default_transaction_deferrable = off 694 | #session_replication_role = 'origin' 695 | #statement_timeout = 0 # in milliseconds, 0 is disabled 696 | #lock_timeout = 0 # in milliseconds, 0 is disabled 697 | #idle_in_transaction_session_timeout = 0 # in milliseconds, 0 is disabled 698 | #idle_session_timeout = 0 # in milliseconds, 0 is disabled 699 | #vacuum_freeze_table_age = 150000000 700 | #vacuum_freeze_min_age = 50000000 701 | #vacuum_failsafe_age = 1600000000 702 | #vacuum_multixact_freeze_table_age = 150000000 703 | #vacuum_multixact_freeze_min_age = 5000000 704 | #vacuum_multixact_failsafe_age = 1600000000 705 | #bytea_output = 'hex' # hex, escape 706 | #xmlbinary = 'base64' 707 | #xmloption = 'content' 708 | #gin_pending_list_limit = 4MB 709 | 710 | # - Locale and Formatting - 711 | 712 | datestyle = 'iso, dmy' 713 | #intervalstyle = 'postgres' 714 | timezone = 'Europe/Moscow' 715 | #timezone_abbreviations = 'Default' # Select the set of available time zone 716 | # abbreviations. Currently, there are 717 | # Default 718 | # Australia (historical usage) 719 | # India 720 | # You can create your own file in 721 | # share/timezonesets/. 722 | #extra_float_digits = 1 # min -15, max 3; any value >0 actually 723 | # selects precise output mode 724 | #client_encoding = sql_ascii # actually, defaults to database 725 | # encoding 726 | 727 | # These settings are initialized by initdb, but they can be changed. 728 | lc_messages = 'Russian_Russia.1251' # locale for system error message 729 | # strings 730 | lc_monetary = 'Russian_Russia.1251' # locale for monetary formatting 731 | lc_numeric = 'Russian_Russia.1251' # locale for number formatting 732 | lc_time = 'Russian_Russia.1251' # locale for time formatting 733 | 734 | # default configuration for text search 735 | default_text_search_config = 'pg_catalog.russian' 736 | 737 | # - Shared Library Preloading - 738 | 739 | #local_preload_libraries = '' 740 | #session_preload_libraries = '' 741 | #shared_preload_libraries = '' # (change requires restart) 742 | #jit_provider = 'llvmjit' # JIT library to use 743 | 744 | # - Other Defaults - 745 | 746 | #dynamic_library_path = '$libdir' 747 | #gin_fuzzy_search_limit = 0 748 | 749 | 750 | #------------------------------------------------------------------------------ 751 | # LOCK MANAGEMENT 752 | #------------------------------------------------------------------------------ 753 | 754 | #deadlock_timeout = 1s 755 | #max_locks_per_transaction = 64 # min 10 756 | # (change requires restart) 757 | #max_pred_locks_per_transaction = 64 # min 10 758 | # (change requires restart) 759 | #max_pred_locks_per_relation = -2 # negative values mean 760 | # (max_pred_locks_per_transaction 761 | # / -max_pred_locks_per_relation) - 1 762 | #max_pred_locks_per_page = 2 # min 0 763 | 764 | 765 | #------------------------------------------------------------------------------ 766 | # VERSION AND PLATFORM COMPATIBILITY 767 | #------------------------------------------------------------------------------ 768 | 769 | # - Previous PostgreSQL Versions - 770 | 771 | #array_nulls = on 772 | #backslash_quote = safe_encoding # on, off, or safe_encoding 773 | #escape_string_warning = on 774 | #lo_compat_privileges = off 775 | #quote_all_identifiers = off 776 | #standard_conforming_strings = on 777 | #synchronize_seqscans = on 778 | 779 | # - Other Platforms and Clients - 780 | 781 | #transform_null_equals = off 782 | 783 | 784 | #------------------------------------------------------------------------------ 785 | # ERROR HANDLING 786 | #------------------------------------------------------------------------------ 787 | 788 | #exit_on_error = off # terminate session on any error? 789 | #restart_after_crash = on # reinitialize after backend crash? 790 | #data_sync_retry = off # retry or panic on failure to fsync 791 | # data? 792 | # (change requires restart) 793 | #recovery_init_sync_method = fsync # fsync, syncfs (Linux 5.8+) 794 | 795 | 796 | #------------------------------------------------------------------------------ 797 | # CONFIG FILE INCLUDES 798 | #------------------------------------------------------------------------------ 799 | 800 | # These options allow settings to be loaded from files other than the 801 | # default postgresql.conf. Note that these are directives, not variable 802 | # assignments, so they can usefully be given more than once. 803 | 804 | #include_dir = '...' # include files ending in '.conf' from 805 | # a directory, e.g., 'conf.d' 806 | #include_if_exists = '...' # include file only if it exists 807 | #include = '...' # include file 808 | 809 | 810 | #------------------------------------------------------------------------------ 811 | # CUSTOMIZED OPTIONS 812 | #------------------------------------------------------------------------------ 813 | 814 | # Add settings for extensions here 815 | -------------------------------------------------------------------------------- /src/build.spec: -------------------------------------------------------------------------------- 1 | a = Analysis(['main.py'], 2 | hiddenimports=[], 3 | hookspath=None, 4 | runtime_hooks=None, 5 | ) 6 | pyz = PYZ(a.pure) 7 | 8 | options = [('u', None, 'OPTION')] 9 | 10 | exe = EXE(pyz, 11 | a.scripts, 12 | a.binaries, 13 | a.zipfiles, 14 | a.datas, 15 | options, 16 | name='1cv8_postgres_helper', 17 | debug=False, 18 | strip=None, 19 | upx=True, 20 | ) 21 | -------------------------------------------------------------------------------- /src/main.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import os 3 | import platform 4 | import time 5 | 6 | from enum import Enum 7 | 8 | 9 | class StorageType(Enum): 10 | ssd = "ssd" 11 | hdd = "hdd" 12 | 13 | def __str__(self): 14 | return self.value 15 | 16 | 17 | parser = argparse.ArgumentParser( 18 | description="Appends additional keyboard layout shortcuts to kitty.conf" 19 | ) 20 | parser.add_argument( 21 | "--config", 22 | type=str, 23 | dest="config", 24 | help="Config file to edit", 25 | ) 26 | parser.add_argument( 27 | "--mem", 28 | type=str, 29 | dest="mem", 30 | help="Amount of RAM dedicated to PostgreSQL. Accepted in PostgreSQL-like notation i.e. 4096MB, 4GB ...", 31 | ) 32 | parser.add_argument( 33 | "--cpu", 34 | type=int, 35 | dest="cpu", 36 | default=os.cpu_count(), 37 | help="CPU core count dedicated to PostgreSQL. Default to all available cores", 38 | ) 39 | parser.add_argument( 40 | "--storage", 41 | type=StorageType, 42 | choices=list(StorageType), 43 | dest="storage", 44 | default=StorageType.ssd, 45 | help="Storage type used for PostgreSQL. Default is ssd", 46 | ) 47 | parser.add_argument( 48 | "--disable-synchronous-commit", 49 | dest="synchronous_commit", 50 | action="store_false", 51 | help="Disabling synchronous commit increase performance in risk of data loss", 52 | ) 53 | parser.add_argument( 54 | "--enable-group-commit", 55 | dest="group_commit", 56 | action="store_true", 57 | help="Enable group commits. Use for >= 1000 TPS instances", 58 | ) 59 | parser.add_argument( 60 | "--no-backup", 61 | dest="backup", 62 | action="store_false", 63 | help="No backup file will be created", 64 | ) 65 | 66 | args = parser.parse_args() 67 | 68 | 69 | def unit_list(radix_suffix: str = ""): 70 | return list( 71 | map(lambda item: item + radix_suffix, ["K", "M", "G", "T", "P", "E", "Z"]) 72 | ) 73 | 74 | 75 | def sizeof_fmt( 76 | value: int, suffix: str = "B", radix: int = 1024, radix_suffix: str = "" 77 | ): 78 | for unit in [""] + unit_list(radix_suffix): 79 | if abs(value) < radix or value % radix > 0: 80 | return f"{value:.0f}{unit}{suffix}" 81 | value /= radix 82 | return f'{value:.0f}{"Y"+ radix_suffix}{suffix}' 83 | 84 | 85 | def sizeof_parse( 86 | value: str, suffix: str = "B", radix: int = 1024, radix_suffix: str = "" 87 | ): 88 | wo_suffix = value.replace(suffix, "") 89 | if wo_suffix.isnumeric(): 90 | return int(wo_suffix) 91 | rank = 1 92 | for unit in unit_list(radix_suffix): 93 | if unit in wo_suffix: 94 | return int(wo_suffix.replace(unit, "")) * (radix**rank) 95 | rank += 1 96 | raise ValueError(f"Couldn't parse value to int: {value}") 97 | 98 | 99 | config_file_path = args.config 100 | config_directory, config_file_name = os.path.split(config_file_path) 101 | 102 | mem = sizeof_parse(args.mem) 103 | cpu = args.cpu 104 | storage = args.storage 105 | 106 | enable_group_commit = args.group_commit 107 | disable_synchronous_commit = not args.synchronous_commit 108 | 109 | shared_buffers = mem / 4 110 | random_page_cost = 1.1 if storage == StorageType.ssd else 2.0 111 | effective_io_concurrency = 2 if storage == StorageType.ssd and platform.system() != "Windows" else 0 112 | 113 | configmap = { 114 | "row_security": "off", 115 | "ssl": "off", 116 | "shared_buffers": sizeof_fmt(shared_buffers), 117 | "temp_buffers": "256MB", 118 | "work_mem": sizeof_fmt(mem / 64), 119 | "maintenance_work_mem": sizeof_fmt(min(mem / 16, 2047 * 2 ** 20)), 120 | "fsync": "on", 121 | "synchronous_commit": "on", 122 | "checkpoint_completion_target": 0.9, 123 | "min_wal_size": "2GB", 124 | "max_wal_size": "4GB", 125 | "commit_delay": 0, 126 | "commit_siblings": 5, 127 | "bgwriter_delay": "20ms", 128 | "bgwriter_lru_multiplier": 4.0, 129 | "bgwriter_lru_maxpages": 400, 130 | "autovacuum": "on", 131 | "autovacuum_max_workers": max(cpu / 4, 4), 132 | "autovacuum_naptime": "20s", 133 | "max_files_per_process": 8000, 134 | "effective_cache_size": sizeof_fmt(mem - shared_buffers), 135 | "random_page_cost": random_page_cost, 136 | "from_collapse_limit": 20, 137 | "join_collapse_limit": 20, 138 | "geqo": "on", 139 | "geqo_threshold": 12, 140 | "effective_io_concurrency": effective_io_concurrency, 141 | "standard_conforming_strings": "off", 142 | "escape_string_warning": "off", 143 | "max_locks_per_transaction": 1000, 144 | "max_connections": 500, 145 | } 146 | 147 | if enable_group_commit: 148 | configmap.update( 149 | { 150 | "commit_delay": 1000, 151 | } 152 | ) 153 | 154 | if disable_synchronous_commit: 155 | configmap.update( 156 | { 157 | "synchronous_commit": "off", 158 | } 159 | ) 160 | 161 | # read config file all lines 162 | with open(config_file_path) as f: 163 | lines = f.readlines() 164 | new_lines = [] 165 | for line in lines: 166 | # if line doesn't contain known parameter 167 | if not any(line.replace("#", "").startswith(f"{key} = ") for key in configmap.keys()): 168 | new_lines.append(line) 169 | continue 170 | # remove comment from line 171 | if line.startswith("#"): 172 | line = line[1:] 173 | line_parts = line.split(" ") 174 | parameter_name = line_parts[0] 175 | new_line = f"{parameter_name} = {configmap[parameter_name]}{os.linesep}" 176 | new_lines.append(new_line) 177 | # create backup 178 | if args.backup: 179 | with open( 180 | os.path.join(config_directory, f"{config_file_name}.{time.time()}.backup"), "w" 181 | ) as f: 182 | f.writelines(lines) 183 | # write new config file 184 | with open(config_file_path, "w") as f: 185 | f.writelines(new_lines) 186 | --------------------------------------------------------------------------------