├── .circleci ├── config.yml ├── custom.sql ├── ddl_create_index.sql ├── ddl_drop_index.sql ├── run.yml ├── sample.log ├── sample.replay ├── test.dump.bz2 ├── test.dump.gz └── test.dump.sql ├── .gitignore ├── LICENSE ├── README.md ├── docker ├── Dockerfile ├── README.md ├── postgresql_10_tweak.conf ├── postgresql_11_tweak.conf ├── postgresql_12_tweak.conf ├── postgresql_9.6_tweak.conf ├── rebuild_push_images.sh └── tsearch_data │ ├── russian.affix │ └── russian.dict ├── help ├── help.sh ├── nancy.md ├── nancy_prepare_workload.md └── nancy_run.md ├── nancy ├── nancy_describe.sh ├── nancy_prepare_workload.sh ├── nancy_run.sh ├── pg_badger_parsing.sh ├── tests ├── nancy_cli_run.sh ├── nancy_cli_run_no_optons.sh ├── nancy_cli_unknown.sh ├── nancy_prepare_workload.sh ├── nancy_run_abnormal.sh ├── nancy_run_aws_no_keys.sh ├── nancy_run_aws_pgdata_dir.sh ├── nancy_run_aws_zfs_i3.sh ├── nancy_run_before_init_code.sh ├── nancy_run_ebs_disk_size.sh ├── nancy_run_ebs_disk_size_incorrect.sh ├── nancy_run_invalid_aws_option.sh ├── nancy_run_invalid_option.sh ├── nancy_run_invalid_spot_duration.sh ├── nancy_run_localhost_connection_str.sh ├── nancy_run_localhost_less_output.sh ├── nancy_run_localhost_norm_output.sh ├── nancy_run_localhost_pgbench.sh ├── nancy_run_localhost_pgdata_dir.sh ├── nancy_run_localhost_real_workload.sh ├── nancy_run_localhost_series.sh ├── nancy_run_localhost_simple_dump.sh ├── nancy_run_localhost_simple_dump_with_index.sh ├── nancy_run_localhost_simple_gz_dump.sh ├── nancy_run_localhost_simple_sql_dump.sh ├── nancy_run_localhost_wildcards.sh ├── nancy_run_options_ddl_do+_undo-.sh ├── nancy_run_options_ddl_do-_undo+.sh ├── nancy_run_options_multi_workloads.sh ├── nancy_run_options_no_dump_snapshot.sh ├── nancy_run_options_no_instance_type.sh ├── nancy_run_too_many_objects.sh └── nancy_run_too_many_workloads.sh └── tools ├── meminfo.sh ├── parse_yaml.sh └── unittest └── parse_yml.sh /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | jobs: 3 | build: 4 | working_directory: ~/nancy 5 | docker: 6 | - image: ubuntu:16.04 7 | steps: 8 | - run: 9 | name: Install software 10 | command: | 11 | apt-get update && apt-get install -y sudo wget jq gawk pgreplay bc \ 12 | && wget get.docker.com -q -S -O - | sudo sh 13 | - checkout 14 | - setup_remote_docker 15 | - run: 16 | name: Install Docker client 17 | command: | 18 | set -x 19 | VER="17.03.0-ce" 20 | curl -L -o /tmp/docker-$VER.tgz https://download.docker.com/linux/static/stable/x86_64/docker-$VER.tgz 21 | tar -xz -C /tmp -f /tmp/docker-$VER.tgz 22 | mv /tmp/docker/* /usr/bin 23 | - run: 24 | name: Tests 25 | command: | 26 | errcount=0 27 | printTail=" " 28 | for f in tests/*.sh; do 29 | printf "$f${printTail:0:-${#f}}" 30 | bash "$f" -H 31 | status=$? 32 | if [ "$status" -ne 0 ]; then 33 | errcount="$(($errcount+1))" 34 | fi 35 | done 36 | if [ "$errcount" -ne 0 ]; then 37 | >&2 echo "Oh no! $errcount tests failed" 38 | exit 1 39 | fi 40 | for f in tools/unittest/*.sh; do 41 | printf "$f${printTail:0:-${#f}}" 42 | bash "$f" -H 43 | status=$? 44 | if [ "$status" -ne 0 ]; then 45 | errcount="$(($errcount+1))" 46 | fi 47 | done 48 | if [ "$errcount" -ne 0 ]; then 49 | >&2 echo "Oh no! $errcount tests failed" 50 | exit 1 51 | fi 52 | 53 | -------------------------------------------------------------------------------- /.circleci/custom.sql: -------------------------------------------------------------------------------- 1 | select count(1) from t1 where id between 555 and 777; 2 | 3 | select count(1) from t1 where val between 0.555 and 0.777; 4 | -------------------------------------------------------------------------------- /.circleci/ddl_create_index.sql: -------------------------------------------------------------------------------- 1 | create index i_speedup on t1 using btree(val); 2 | -------------------------------------------------------------------------------- /.circleci/ddl_drop_index.sql: -------------------------------------------------------------------------------- 1 | drop index i_speedup; 2 | -------------------------------------------------------------------------------- /.circleci/run.yml: -------------------------------------------------------------------------------- 1 | run: 2 | 0: 3 | delta_ddl_do: select now(); select now(); 4 | delta_ddl_undo: select now(); 5 | # delta_config: max_wal_size = 2048MB 6 | 1: 7 | # delta_ddl_do: select now(); 8 | # delta_ddl_undo: select now(); 9 | delta_config: max_wal_size = 4092MB 10 | 2: 11 | # delta_ddl_do: select now(); 12 | # delta_ddl_undo: select now(); 13 | delta_config: max_wal_size = 4092MB 14 | -------------------------------------------------------------------------------- /.circleci/sample.log: -------------------------------------------------------------------------------- 1 | 2018-07-12 22:47:06.085 UTC,"testci","testci",2460,"127.0.0.1:53862",5b47da68.99c,6,"idle",2018-07-12 22:47:04 UTC,,0,LOG,00000,"disconnection: session time: 0:00:01.185 user=testci database=testci host=127.0.0.1 port=53862",,,,,,,,,"" 2 | 2018-07-12 22:47:06.302 UTC,,,2473,"127.0.0.1:53865",5b47da6a.9a9,1,"",2018-07-12 22:47:06 UTC,,0,LOG,00000,"connection received: host=127.0.0.1 port=53865",,,,,,,,,"" 3 | 2018-07-12 22:47:07.394 UTC,"testci","testci",28569,"127.0.0.1:53615",5b47d84e.6f99,15,"idle",2018-07-12 22:38:06 UTC,,0,LOG,00000,"disconnection: session time: 0:09:00.762 user=testci database=testci host=127.0.0.1 port=53615",,,,,,,,,"" 4 | 2018-07-12 22:47:07.838 UTC,"testci","testci",2473,"127.0.0.1:53865",5b47da6a.9a9,4,"SELECT",2018-07-12 22:47:06 UTC,12/0,0,LOG,00000,"duration: 14.564 ms statement: select count(*) 5 | from ""hello_world"" as t 6 | order by t.id desc limit 26",,,,,,,,,"" 7 | 2018-07-12 22:47:08.053 UTC,"testci","testci",2473,"127.0.0.1:53865",5b47da6a.9a9,5,"SELECT",2018-07-12 22:47:06 UTC,12/0,0,LOG,00000,"duration: 43.544 ms statement: SELECT * FROM ""hello_world"" ""t"" WHERE i > 0 ORDER BY random()",,,,,,,,,"" 8 | 2018-07-12 22:47:08.547 UTC,"testci","testci",2473,"127.0.0.1:53865",5b47da6a.9a9,6,"idle",2018-07-12 22:47:06 UTC,,0,LOG,00000,"disconnection: session time: 0:00:02.245 user=testci database=testci host=127.0.0.1 port=53865",,,,,,,,,"" 9 | 2018-07-12 22:47:19.218 UTC,,,2642,"127.0.0.1:54013",5b47da77.a52,1,"",2018-07-12 22:47:19 UTC,,0,LOG,00000,"connection received: host=127.0.0.1 port=54013",,,,,,,,,"" 10 | 2018-07-12 22:47:19.218 UTC,,,2643,"127.0.0.1:54014",5b47da77.a53,1,"",2018-07-12 22:47:19 UTC,,0,LOG,00000,"connection received: host=127.0.0.1 port=54014",,,,,,,,,"" 11 | 2018-07-12 22:47:19.218 UTC,,,2644,"127.0.0.1:54015",5b47da77.a54,1,"",2018-07-12 22:47:19 UTC,,0,LOG,00000,"connection received: host=127.0.0.1 port=54015",,,,,,,,,"" 12 | 2018-07-12 22:47:19.226 UTC,"testci","testci",2644,"127.0.0.1:54015",5b47da77.a54,2,"authentication",2018-07-12 22:47:19 UTC,11/77223,0,LOG,00000,"connection authorized: user=testci database=testci SSL enabled (protocol=TLSv1.2, cipher=ECDHE-RSA-AES256-GCM-SHA384, compression=off)",,,,,,,,,"" 13 | 2018-07-12 22:47:19.227 UTC,"testci","testci",2642,"127.0.0.1:54013",5b47da77.a52,2,"authentication",2018-07-12 22:47:19 UTC,12/323914,0,LOG,00000,"connection authorized: user=testci database=testci SSL enabled (protocol=TLSv1.2, cipher=ECDHE-RSA-AES256-GCM-SHA384, compression=off)",,,,,,,,,"" 14 | 2018-07-12 22:47:19.227 UTC,"testci","testci",2643,"127.0.0.1:54014",5b47da77.a53,2,"authentication",2018-07-12 22:47:19 UTC,13/6385,0,LOG,00000,"connection authorized: user=testci database=testci SSL enabled (protocol=TLSv1.2, cipher=ECDHE-RSA-AES256-GCM-SHA384, compression=off)",,,,,,,,,"" 15 | 2018-07-12 22:47:25.491 UTC,"testci","testci",2687,"127.0.0.1:54016",5b47da7a.a7f,3,"idle",2018-07-12 22:47:22 UTC,,0,LOG,00000,"disconnection: session time: 0:00:02.680 user=testci database=testci host=127.0.0.1 port=54016",,,,,,,,,"" 16 | -------------------------------------------------------------------------------- /.circleci/sample.replay: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/postgres-ai/nancy/4b0932165043ab4b4646b7e3f2d1b9a53808ac8f/.circleci/sample.replay -------------------------------------------------------------------------------- /.circleci/test.dump.bz2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/postgres-ai/nancy/4b0932165043ab4b4646b7e3f2d1b9a53808ac8f/.circleci/test.dump.bz2 -------------------------------------------------------------------------------- /.circleci/test.dump.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/postgres-ai/nancy/4b0932165043ab4b4646b7e3f2d1b9a53808ac8f/.circleci/test.dump.gz -------------------------------------------------------------------------------- /.circleci/test.dump.sql: -------------------------------------------------------------------------------- 1 | create table t1 as 2 | select i as id, random() val 3 | from generate_series(1, 1000000) _(i); 4 | 5 | alter table t1 add primary key (id); 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .circleci/tmp 2 | docker/tmp 3 | *.gz 4 | *.json 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2018, Nikolay Samokhvalov 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Postgres.AI 2 |   3 | [![GitHub code size in bytes](https://img.shields.io/github/languages/code-size/badges/shields.svg)](github.com/postgres-ai/nancy) 4 |   5 | 6 |   7 | [![CircleCI](https://circleci.com/gh/postgres-ai/nancy.svg?style=svg)](https://circleci.com/gh/postgres-ai/nancy) 8 | 9 | :warning: Nancy CLI project is on hold now. See details: https://gitlab.com/postgres-ai/nancy/-/issues/228 10 | 11 | # About 12 | 13 | 14 | Nancy helps to conduct automated database experiments. 15 | 16 | The Nancy Command Line Interface is a unified way to manage automated 17 | database experiments either in clouds or on-premise. 18 | 19 | ### What is a Database Experiment? 20 | 21 | Database experiment is a set of actions performed to test 22 | * (a) specified SQL queries ("workload") 23 | * (b) on specified machine / OS / Postgres version ("environment") 24 | * (c) against specified database ("object") 25 | * (d) with an optional change – some DDL or config change ("target" or "delta"). 26 | 27 | Two main goals for any database experiment: 28 | * (1) validation – check that the specified workload is valid, 29 | * (2) benchmark – perform deep SQL query analysis. 30 | 31 | Database experiments are needed when you: 32 | - add or remove indexes; 33 | - for a new DB schema change, want to validate it and estimate migration time; 34 | - want to verify some query optimization ideas; 35 | - tune database configuration parameters; 36 | - do capacity planning and want to stress-test your DB in some environment; 37 | - plan to upgrade your DBMS to a new major version; 38 | - want to train ML model related to DB optimization. 39 | 40 | # Currently Supported Features 41 | 42 | * Works anywhere where Docker can run (checked: Linux Ubuntu/Debian, macOS) 43 | * Experiments are conducted in a Docker container with extended Postgres setup 44 | * Supported Postgres versions: 12 (default), 11, 10, 9.6 45 | * Postgres config specified via options, may be partial 46 | * Supported locations for experimental runs: 47 | * Any machine with Docker installed 48 | * AWS EC2: 49 | * Run on AWS EC2 Spot Instances (using Docker Machine) 50 | * Allow to specify EC2 instance type 51 | * Auto-detect and use current lowest EC2 Spot Instance prices 52 | * Support i3 instances (with NVMe SSD drives) 53 | * Support arbitrary-size EBS volumes 54 | * Support local or remote (S3) files – config, dump, etc 55 | * The object (database) can be specified in various ways: 56 | * Plain text 57 | * Synthetic database generated by [pgbench](https://www.postgresql.org/docs/current/static/pgbench.html) 58 | * Dump file (.sql, .gz, .bz2) 59 | * What to test (a.k.a. "target" or "delta"): 60 | * Test Postgres parameters change 61 | * Test DDL change (specified as "do" and "undo" SQL to return state) 62 | * Supported types of workload: 63 | * Any custom SQL 64 | * Synthetic workload generated by [pgbench](https://www.postgresql.org/docs/current/static/pgbench.html) 65 | * "Real workload" based on Postgres logs (using [pgreplay](https://github.com/laurenz/pgreplay)) 66 | * For "real workload", allow replaying it with increased speed 67 | * Allow to keep container alive for specified time after all steps are done 68 | * Collected artifacts: 69 | * `pg_stat_statements` snapshot 70 | * `pg_stat_database`, ... 71 | * Workload SQL logs 72 | * Deep SQL query analysis report 73 | 74 | # Requirements 75 | 76 | 1) To use Nancy CLI you need Linux or MacOS with installed Docker. 77 | 78 | 2) To run on AWS EC2 instances, you also need: 79 | * AWS CLI https://aws.amazon.com/en/cli/ 80 | * Docker Machine https://docs.docker.com/machine/ 81 | * jq https://stedolan.github.io/jq/ 82 | 83 | 84 | # Installation 85 | 86 | In the minimal configuration, only a few steps are needed: 87 | 88 | NOTICE: The [Additional notes](#additional-notes) section contains 89 | instructions useful in case of docker-related errors during `nancy run` calls. 90 | Alternatively, see Docker's official [post-installation instructions for Linux](https://docs.docker.com/install/linux/linux-postinstall/). 91 | 92 | 1) Install Docker 93 | 94 | Ubuntu/Debian: 95 | ```shell 96 | sudo apt-get -y install docker 97 | sudo systemctl enable docker 98 | sudo systemctl start docker 99 | ``` 100 | 101 | RHEL7: 102 | ```shell 103 | yum -y install docker 104 | systemctl enable docker 105 | systemctl start docker 106 | ``` 107 | 108 | MacOS (assuming that [Homebrew](https://brew.sh/) is installed): 109 | ```shell 110 | brew install docker 111 | ``` 112 | See also: https://docs.docker.com/docker-for-mac/install/ 113 | 114 | 2) Clone this repo and adjust `$PATH`: 115 | ```shell 116 | git clone https://gitlab.com/postgres.ai/nancy.git 117 | echo "export PATH=\$PATH:"$(pwd)"/nancy" >> ~/.bashrc 118 | source ~/.bashrc 119 | ``` 120 | 121 | 3) Install jq 122 | - Ubuntu/Debian: `sudo apt-get -y install jq` 123 | - CentOS/RHEL: `sudo yum install jq` 124 | - MacOS: `brew install jq` 125 | 126 | Additionally, to allow use of AWS EC2 instances: 127 | 128 | 4) Install AWS CLI https://docs.aws.amazon.com/cli/latest/userguide/installing.html 129 | 130 | 5) Install Docker Machine tools https://docs.docker.com/machine/install-machine/ 131 | 132 | # Getting started 133 | 134 | Start with these commands: 135 | ```shell 136 | nancy help 137 | nancy run help 138 | ``` 139 | 140 | # "Hello World!" 141 | 142 | Locally, on any Linux or macOS machine: 143 | ```shell 144 | echo "create table hello_world as select i from generate_series(1, (10^6)::int) _(i);" \ 145 | | bzip2 > ./sample.dump.bz2 146 | 147 | # "Clean run": w/o index 148 | # (seqscan is expected, total time ~150ms, depending on resources) 149 | nancy run \ 150 | --db-dump file://$(pwd)/sample.dump.bz2 \ 151 | --workload-custom-sql "select i from hello_world where i between 10 and 20;" 152 | 153 | # Now check how a regular btree index affects performance 154 | # (expected total time: ~0.05ms) 155 | nancy run \ 156 | --db-dump file://$(pwd)/sample.dump.bz2 \ 157 | --workload-custom-sql "select i from hello_world where i between 10 and 20;" \ 158 | --delta-sql-do "create index i_hello_world_i on hello_world(i);" \ 159 | --delta-sql-undo "drop index i_hello_world_i;" 160 | ``` 161 | 162 | AWS EC2: 163 | ```shell 164 | nancy run \ 165 | --run-on aws \ 166 | --aws-ec2-type "i3.large" \ 167 | --aws-keypair-name awskey \ 168 | --aws-ssh-key-path file://$(echo ~)/.ssh/awskey.pem \ 169 | --db-dump "create table hello_world as select i from generate_series(1, (10^6)::int) _(i);" \ 170 | --workload-custom-sql "select i from hello_world where i between 10 and 20;" 171 | ``` 172 | 173 | # Additional notes 174 | 175 | On Linux, if you experience issues with running (locally) `nancy run` inside `screen` or 176 | `tmux`, double-check that Docker is running and add your user to the `docker` 177 | group, as described below. See also: https://docs.docker.com/install/linux/linux-postinstall/. 178 | 179 | Ubuntu/Debian: 180 | ```shell 181 | # Ubuntu/Debian 182 | sudo usermod -aG docker ${USER} 183 | newgrp docker 184 | ``` 185 | 186 | CentOS/RHEL: 187 | ```shell 188 | sudo usermod -aG dockerroot ${USER} 189 | newgrp dockerroot 190 | ``` 191 | 192 | On MacOS, it is recommended to specify `--tmp-path` explicitly, similar to this: 193 | ``` 194 | mkdir ./tmp 195 | nancy run ... --tmp-path "$(pwd)/tmp" 196 | ``` 197 | -------------------------------------------------------------------------------- /docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:18.04 2 | 3 | ARG PG_SERVER_VERSION 4 | 5 | ENV PG_SERVER_VERSION=${PG_SERVER_VERSION:-12} \ 6 | DEBIAN_FRONTEND=noninteractive 7 | 8 | # add custom FTS dictionaries 9 | ADD ./tsearch_data /usr/share/postgresql/${PG_SERVER_VERSION}/tsearch_data 10 | 11 | # logging ON; memory setting – for 2CPU/4096MB/SSD 12 | ADD ./postgresql_${PG_SERVER_VERSION}_tweak.conf /postgresql.tweak.conf 13 | 14 | # set up apt, add Postgres repo 15 | RUN apt-get update 16 | RUN apt-get install -y wget ca-certificates gnupg2 17 | RUN wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - 18 | RUN echo "deb http://apt.postgresql.org/pub/repos/apt/ bionic-pgdg main" >> /etc/apt/sources.list.d/pgdg.list 19 | RUN apt-get update 20 | RUN apt-get install -y apt-utils 21 | 22 | # install additional utilites 23 | RUN apt-get install -y sudo git jq libjson-xs-perl vim 24 | RUN apt-get install -y sysbench s3cmd sudo bzip2 software-properties-common 25 | RUN apt-get install -y sysstat iotop moreutils psmisc 26 | 27 | # install Postgres and postgres-specific packages 28 | RUN apt-get install -y postgresql-${PG_SERVER_VERSION} 29 | RUN apt-get install -y postgresql-contrib-${PG_SERVER_VERSION} 30 | RUN apt-get install -y postgresql-server-dev-${PG_SERVER_VERSION} 31 | #RUN if [ "${PG_SERVER_VERSION}" != "12" ]; then apt-get install -y postgresql-${PG_SERVER_VERSION}-dbg; fi 32 | RUN apt-get install -y postgresql-${PG_SERVER_VERSION}-pg-stat-kcache 33 | RUN apt-get install -y postgresql-client-12 34 | RUN if [ "${PG_SERVER_VERSION}" == "12" ]; then apt-get install -y postgresql-plpython3-${PG_SERVER_VERSION}; fi 35 | RUN if [ "${PG_SERVER_VERSION}" != "12" ]; then apt-get install -y postgresql-plpython-${PG_SERVER_VERSION}; fi 36 | 37 | RUN apt-get install -y pgreplay 38 | RUN apt-get update && apt-get install -y pspg 39 | RUN git clone https://github.com/NikolayS/postgres_dba.git /root/postgres_dba 40 | RUN apt-get install -y postgresql-${PG_SERVER_VERSION}-repack 41 | RUN git clone https://github.com/darold/pgbadger.git /root/pgbadger && cd /root/pgbadger && git checkout "tags/v11.1" 42 | 43 | # install FlameGraph and generic perf 44 | RUN git clone https://github.com/brendangregg/FlameGraph /root/FlameGraph 45 | RUN apt-get install -y linux-tools-generic 46 | # replace incorrect Debian perf wrapper with a symbolic link 47 | RUN path=$(ls /usr/lib/linux-tools/*generic/perf | head -n 1) && ln -s -f "$path" /usr/bin/perf 48 | 49 | # configure psql, configure Postgres 50 | RUN echo "\\set dba '\\\\\\\\i /root/postgres_dba/start.psql'" >> ~/.psqlrc 51 | RUN echo "\\setenv PAGER 'pspg -bX --no-mouse'" >> ~/.psqlrc 52 | RUN echo "local all all trust" > /etc/postgresql/${PG_SERVER_VERSION}/main/pg_hba.conf 53 | RUN echo "host all all 0.0.0.0/0 md5" >> /etc/postgresql/${PG_SERVER_VERSION}/main/pg_hba.conf 54 | RUN echo "listen_addresses='*'" >> /etc/postgresql/${PG_SERVER_VERSION}/main/postgresql.conf 55 | RUN echo "log_filename='postgresql-${PG_SERVER_VERSION}-main.log'" >> /etc/postgresql/${PG_SERVER_VERSION}/main/postgresql.conf 56 | 57 | # prepare database 'test' with 'testuser' 58 | RUN /etc/init.d/postgresql start && psql -U postgres -c "create database test" \ 59 | && psql -U postgres -d test -c "CREATE EXTENSION pg_repack" \ 60 | && psql -U postgres -c "CREATE ROLE testuser LOGIN password 'testuser' superuser" && /etc/init.d/postgresql stop 61 | 62 | # apply 'tweaked' config 63 | RUN cat /postgresql.tweak.conf >> /etc/postgresql/${PG_SERVER_VERSION}/main/postgresql.conf 64 | 65 | # prepare Postgres start script 66 | RUN echo "#!/bin/bash" > /pg_start.sh && chmod a+x /pg_start.sh 67 | RUN printf "sudo -u postgres /usr/lib/postgresql/${PG_SERVER_VERSION}/bin/postgres -D /var/lib/postgresql/${PG_SERVER_VERSION}/main -c config_file=/etc/postgresql/${PG_SERVER_VERSION}/main/postgresql.conf \n" >> /pg_start.sh 68 | # infinite sleep to allow restarting Postgres 69 | RUN echo "/bin/bash -c \"trap : TERM INT; sleep infinity & wait\"" >> /pg_start.sh 70 | 71 | # generate english locale for iostat + iostat-tool 72 | RUN locale-gen en_US.UTF-8 73 | 74 | # install pip and iostat-tool 75 | RUN apt-get install -y curl 76 | RUN curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py 77 | RUN python3 get-pip.py 78 | RUN pip3 install iostat-tool 79 | 80 | # install zfs utils 81 | RUN apt-get install -y zfsutils-linux 82 | 83 | # reduce images size 84 | RUN rm -rf /tmp/* 85 | RUN apt-get purge -y --auto-remove 86 | RUN apt-get clean -y autoclean 87 | RUN rm -rf /var/lib/apt/lists/* 88 | 89 | EXPOSE 5432 90 | 91 | #VOLUME ["/etc/postgresql", "/var/log/postgresql", "/var/lib/postgresql"] 92 | 93 | CMD ["/pg_start.sh"] 94 | -------------------------------------------------------------------------------- /docker/README.md: -------------------------------------------------------------------------------- 1 | How to build/rebuild: 2 | 3 | Rebuild and push images for all postgres versions: 4 | ```bash 5 | ./rebuild_push_images.sh 6 | ``` 7 | 8 | Or do it manually: 9 | ```bash 10 | export NANCY_DOCKER_PG_VERSION=9.6 11 | 12 | docker build \ 13 | --build-arg "PG_SERVER_VERSION=${NANCY_DOCKER_PG_VERSION}" \ 14 | -t "postgresmen/postgres-nancy:${NANCY_DOCKER_PG_VERSION}" . 15 | 16 | docker login # you must be registered, go to hub.docker.com 17 | 18 | docker push "postgresmen/postgres-nancy:${NANCY_DOCKER_PG_VERSION}" 19 | ``` 20 | -------------------------------------------------------------------------------- /docker/postgresql_10_tweak.conf: -------------------------------------------------------------------------------- 1 | # IMPORTANT: on faster systems, you need to use your own memory-related settings! 2 | statement_timeout = 0 3 | 4 | log_destination = 'stderr,csvlog' 5 | logging_collector = on 6 | log_directory = '/var/log/postgresql' 7 | # log_filename – to be set dynamically 8 | log_min_messages = notice 9 | log_min_error_statement = notice 10 | log_min_duration_statement = -1 # rely on "auto_explain.log_min_duration = 0", avoid duplicates 11 | log_checkpoints = on 12 | log_connections = on 13 | log_disconnections = on 14 | log_line_prefix = '%t [%p]: [%l-1] db=%d,user=%u (%a,%h) ' 15 | log_lock_waits = on 16 | log_replication_commands = on 17 | log_temp_files = 0 18 | log_autovacuum_min_duration = 0 19 | 20 | shared_preload_libraries = 'pg_stat_statements,auto_explain,pg_stat_kcache' 21 | 22 | pg_stat_statements.max = 5000 23 | pg_stat_statements.track = all 24 | pg_stat_statements.track_utility = on 25 | pg_stat_statements.save = on 26 | 27 | auto_explain.log_min_duration = 0 28 | auto_explain.log_analyze = on 29 | auto_explain.log_verbose = on 30 | auto_explain.log_buffers = on 31 | auto_explain.log_format = 'json' 32 | auto_explain.log_timing = on 33 | auto_explain.log_triggers = on 34 | auto_explain.log_nested_statements = on 35 | -------------------------------------------------------------------------------- /docker/postgresql_11_tweak.conf: -------------------------------------------------------------------------------- 1 | # IMPORTANT: on faster systems, you need to use your own memory-related settings! 2 | statement_timeout = 0 3 | 4 | log_destination = 'stderr,csvlog' 5 | logging_collector = on 6 | log_directory = '/var/log/postgresql' 7 | # log_filename – to be set dynamically 8 | log_min_messages = notice 9 | log_min_error_statement = notice 10 | log_min_duration_statement = -1 # rely on "auto_explain.log_min_duration = 0", avoid duplicates 11 | log_checkpoints = on 12 | log_connections = on 13 | log_disconnections = on 14 | log_line_prefix = '%t [%p]: [%l-1] db=%d,user=%u (%a,%h) ' 15 | log_lock_waits = on 16 | log_replication_commands = on 17 | log_temp_files = 0 18 | log_autovacuum_min_duration = 0 19 | 20 | shared_preload_libraries = 'pg_stat_statements,auto_explain,pg_stat_kcache' 21 | 22 | pg_stat_statements.max = 5000 23 | pg_stat_statements.track = all 24 | pg_stat_statements.track_utility = on 25 | pg_stat_statements.save = on 26 | 27 | auto_explain.log_min_duration = 0 28 | auto_explain.log_analyze = on 29 | auto_explain.log_verbose = on 30 | auto_explain.log_buffers = on 31 | auto_explain.log_format = 'json' 32 | auto_explain.log_timing = on 33 | auto_explain.log_triggers = on 34 | auto_explain.log_nested_statements = on 35 | -------------------------------------------------------------------------------- /docker/postgresql_12_tweak.conf: -------------------------------------------------------------------------------- 1 | # IMPORTANT: on faster systems, you need to use your own memory-related settings! 2 | statement_timeout = 0 3 | 4 | log_destination = 'stderr,csvlog' 5 | logging_collector = on 6 | log_directory = '/var/log/postgresql' 7 | # log_filename – to be set dynamically 8 | log_min_messages = notice 9 | log_min_error_statement = notice 10 | log_min_duration_statement = -1 # rely on "auto_explain.log_min_duration = 0", avoid duplicates 11 | log_checkpoints = on 12 | log_connections = on 13 | log_disconnections = on 14 | log_line_prefix = '%t [%p]: [%l-1] db=%d,user=%u (%a,%h) ' 15 | log_lock_waits = on 16 | log_replication_commands = on 17 | log_temp_files = 0 18 | log_autovacuum_min_duration = 0 19 | 20 | shared_preload_libraries = 'pg_stat_statements,auto_explain,pg_stat_kcache' 21 | 22 | pg_stat_statements.max = 5000 23 | pg_stat_statements.track = all 24 | pg_stat_statements.track_utility = on 25 | pg_stat_statements.save = on 26 | 27 | auto_explain.log_min_duration = 0 28 | auto_explain.log_analyze = on 29 | auto_explain.log_verbose = on 30 | auto_explain.log_buffers = on 31 | auto_explain.log_format = 'json' 32 | auto_explain.log_timing = on 33 | auto_explain.log_triggers = on 34 | auto_explain.log_nested_statements = on 35 | -------------------------------------------------------------------------------- /docker/postgresql_9.6_tweak.conf: -------------------------------------------------------------------------------- 1 | # IMPORTANT: on faster systems, you need to use your own memory-related settings! 2 | statement_timeout = 0 3 | 4 | log_destination = 'stderr,csvlog' 5 | logging_collector = on 6 | log_directory = '/var/log/postgresql' 7 | # log_filename – to be set dynamically 8 | log_min_messages = notice 9 | log_min_error_statement = notice 10 | log_min_duration_statement = -1 # rely on "auto_explain.log_min_duration = 0", avoid duplicates 11 | log_checkpoints = on 12 | log_connections = on 13 | log_disconnections = on 14 | log_line_prefix = '%t [%p]: [%l-1] db=%d,user=%u (%a,%h) ' 15 | log_lock_waits = on 16 | log_replication_commands = on 17 | log_temp_files = 0 18 | log_autovacuum_min_duration = 0 19 | 20 | shared_preload_libraries = 'pg_stat_statements,auto_explain,pg_stat_kcache' 21 | 22 | pg_stat_statements.max = 5000 23 | pg_stat_statements.track = all 24 | pg_stat_statements.track_utility = on 25 | pg_stat_statements.save = on 26 | 27 | auto_explain.log_min_duration = 0 28 | auto_explain.log_analyze = on 29 | auto_explain.log_verbose = on 30 | auto_explain.log_buffers = on 31 | auto_explain.log_format = 'json' 32 | auto_explain.log_timing = on 33 | auto_explain.log_triggers = on 34 | auto_explain.log_nested_statements = on 35 | -------------------------------------------------------------------------------- /docker/rebuild_push_images.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Rebuild all images and push to Docker Hub 3 | set -e -u -o pipefail 4 | 5 | VERSIONS="9.6 10 11 12" 6 | 7 | if [[ ! -z ${1+x} ]]; then 8 | VERSIONS="$1" 9 | fi 10 | 11 | # support of CI secrets (login & password for Docker Hub registry) 12 | if [[ ! -z ${DOCKER_LOGIN+x} ]] && [[ ! -z ${DOCKER_PASSWORD+x} ]]; then 13 | docker login --username "${DOCKER_LOGIN}" --password "${DOCKER_PASSWORD}" 14 | else 15 | # you must be loged in with Docker Desktop 16 | docker login 17 | fi 18 | 19 | for version in $VERSIONS; do 20 | docker build \ 21 | --build-arg "PG_SERVER_VERSION=${version}" \ 22 | -t "postgresmen/postgres-nancy:${version}" . 23 | 24 | docker push "postgresmen/postgres-nancy:${version}" 25 | done 26 | 27 | 28 | -------------------------------------------------------------------------------- /docker/tsearch_data/russian.affix: -------------------------------------------------------------------------------- 1 | SET KOI8-R 2 | 3 | SFX Z Y 4 4 | SFX Z ый о [лнртв]ый 5 | SFX Z ий о ький 6 | SFX Z ий и [цс]кий 7 | SFX Z ий е щий 8 | 9 | SFX Y Y 435 10 | SFX Y чь жешь чь 11 | SFX Y чь жете чь 12 | SFX Y чь жет чь 13 | SFX Y чь жем чь 14 | SFX Y чь гут чь 15 | SFX Y чь гу чь 16 | SFX Y заться жутся заться 17 | SFX Y заться жусь заться 18 | SFX Y заться жешься заться 19 | SFX Y заться жется заться 20 | SFX Y заться жетесь заться 21 | SFX Y заться жемся заться 22 | SFX Y зать жут зать 23 | SFX Y зать жу зать 24 | SFX Y зать жешь зать 25 | SFX Y зать жете зать 26 | SFX Y зать жет зать 27 | SFX Y зать жем зать 28 | SFX Y ыться удутся быться 29 | SFX Y ыться удусь быться 30 | SFX Y ыться удешься быться 31 | SFX Y ыться удется быться 32 | SFX Y ыться удетесь быться 33 | SFX Y ыться удемся быться 34 | SFX Y ыть удут быть 35 | SFX Y ыть уду быть 36 | SFX Y ыть удешь быть 37 | SFX Y ыть удете быть 38 | SFX Y ыть удет быть 39 | SFX Y ыть удем быть 40 | SFX Y ваться овутся зваться 41 | SFX Y ваться овусь зваться 42 | SFX Y ваться овешься зваться 43 | SFX Y ваться овется зваться 44 | SFX Y ваться оветесь зваться 45 | SFX Y ваться овемся зваться 46 | SFX Y ваться овёшься зваться 47 | SFX Y ваться овётся зваться 48 | SFX Y ваться овётесь зваться 49 | SFX Y ваться овёмся зваться 50 | SFX Y вать овут звать 51 | SFX Y вать ову звать 52 | SFX Y вать овешь звать 53 | SFX Y вать овете звать 54 | SFX Y вать овет звать 55 | SFX Y вать овем звать 56 | SFX Y вать овёшь звать 57 | SFX Y вать овёте звать 58 | SFX Y вать овёт звать 59 | SFX Y вать овём звать 60 | SFX Y жаться гутся жаться 61 | SFX Y жаться гусь жаться 62 | SFX Y жать гут жать 63 | SFX Y жать гу жать 64 | SFX Y ться шься даться 65 | SFX Y ться вутся лыться 66 | SFX Y ться вусь лыться 67 | SFX Y ться вешься лыться 68 | SFX Y ться вется лыться 69 | SFX Y ться ветесь лыться 70 | SFX Y ться вемся лыться 71 | SFX Y ться вёшься лыться 72 | SFX Y ться вётся лыться 73 | SFX Y ться вётесь лыться 74 | SFX Y ться вёмся лыться 75 | SFX Y ться стся даться 76 | SFX Y ться нутся статься 77 | SFX Y ться нусь статься 78 | SFX Y ться нешься статься 79 | SFX Y ться нется статься 80 | SFX Y ться нетесь статься 81 | SFX Y ться немся статься 82 | SFX Y ться мся даться 83 | SFX Y ться дутся даться 84 | SFX Y ться дитесь даться 85 | SFX Y ться димся даться 86 | SFX Y ть шь дать 87 | SFX Y ть вут лыть 88 | SFX Y ть ву лыть 89 | SFX Y ть вешь лыть 90 | SFX Y ть вете лыть 91 | SFX Y ть вет лыть 92 | SFX Y ть вем лыть 93 | SFX Y ть вёшь лыть 94 | SFX Y ть вёте лыть 95 | SFX Y ть вёт лыть 96 | SFX Y ть вём лыть 97 | SFX Y ть ут лезть 98 | SFX Y ть у лезть 99 | SFX Y ть ст дать 100 | SFX Y ть нут стать 101 | SFX Y ть ну стать 102 | SFX Y ть нешь стать 103 | SFX Y ть нете стать 104 | SFX Y ть нет стать 105 | SFX Y ть нем стать 106 | SFX Y ть м дать 107 | SFX Y ть ешь лезть 108 | SFX Y ть ете лезть 109 | SFX Y ть ет лезть 110 | SFX Y ть ем лезть 111 | SFX Y ть дут дать 112 | SFX Y ть дите дать 113 | SFX Y ть дим дать 114 | SFX Y таться чутся [^с]таться 115 | SFX Y таться чусь [^с]таться 116 | SFX Y таться чешься [^с]таться 117 | SFX Y таться чется [^с]таться 118 | SFX Y таться четесь [^с]таться 119 | SFX Y таться чемся [^с]таться 120 | SFX Y тать чут [^с]тать 121 | SFX Y тать чу [^с]тать 122 | SFX Y тать чешь [^с]тать 123 | SFX Y тать чете [^с]тать 124 | SFX Y тать чет [^с]тать 125 | SFX Y тать чем [^с]тать 126 | SFX Y сться дутся асться 127 | SFX Y сться дусь асться 128 | SFX Y сться дешься асться 129 | SFX Y сться дется асться 130 | SFX Y сться детесь асться 131 | SFX Y сться демся асться 132 | SFX Y сться дёшься асться 133 | SFX Y сться дётся асться 134 | SFX Y сться дётесь асться 135 | SFX Y сться дёмся асться 136 | SFX Y сть дут асть 137 | SFX Y сть ду асть 138 | SFX Y сть дешь асть 139 | SFX Y сть дете асть 140 | SFX Y сть дет асть 141 | SFX Y сть дем асть 142 | SFX Y сть дёшь асть 143 | SFX Y сть дёте асть 144 | SFX Y сть дёт асть 145 | SFX Y сть дём асть 146 | SFX Y стись тутся лестись 147 | SFX Y стись тусь лестись 148 | SFX Y стись тешься лестись 149 | SFX Y стись тется лестись 150 | SFX Y стись тетесь лестись 151 | SFX Y стись темся лестись 152 | SFX Y стись тёшься лестись 153 | SFX Y стись тётся лестись 154 | SFX Y стись тётесь лестись 155 | SFX Y стись тёмся лестись 156 | SFX Y стись дутся вестись 157 | SFX Y стись дусь вестись 158 | SFX Y стись дешься вестись 159 | SFX Y стись дется вестись 160 | SFX Y стись детесь вестись 161 | SFX Y стись демся вестись 162 | SFX Y стись дёшься вестись 163 | SFX Y стись дётся вестись 164 | SFX Y стись дётесь вестись 165 | SFX Y стись дёмся вестись 166 | SFX Y сти тут лести 167 | SFX Y сти ту лести 168 | SFX Y сти тешь лести 169 | SFX Y сти тете лести 170 | SFX Y сти тет лести 171 | SFX Y сти тем лести 172 | SFX Y сти тёшь лести 173 | SFX Y сти тёте лести 174 | SFX Y сти тёт лести 175 | SFX Y сти тём лести 176 | SFX Y сти дут вести 177 | SFX Y сти ду вести 178 | SFX Y сти дешь вести 179 | SFX Y сти дете вести 180 | SFX Y сти дет вести 181 | SFX Y сти дем вести 182 | SFX Y сти дёшь вести 183 | SFX Y сти дёте вести 184 | SFX Y сти дёт вести 185 | SFX Y сти дём вести 186 | SFX Y сти бут рести 187 | SFX Y сти бу рести 188 | SFX Y сти бешь рести 189 | SFX Y сти бете рести 190 | SFX Y сти бет рести 191 | SFX Y сти бем рести 192 | SFX Y сти бёшь рести 193 | SFX Y сти бёте рести 194 | SFX Y сти бёт рести 195 | SFX Y сти бём рести 196 | SFX Y слаться шлешься слаться 197 | SFX Y слаться шлется слаться 198 | SFX Y слаться шлетесь слаться 199 | SFX Y слаться шлемся слаться 200 | SFX Y слаться шлются слаться 201 | SFX Y слаться шлюсь слаться 202 | SFX Y слаться шлёшься слаться 203 | SFX Y слаться шлётся слаться 204 | SFX Y слаться шлётесь слаться 205 | SFX Y слаться шлёмся слаться 206 | SFX Y слать шлешь слать 207 | SFX Y слать шлете слать 208 | SFX Y слать шлет слать 209 | SFX Y слать шлем слать 210 | SFX Y слать шлют слать 211 | SFX Y слать шлю слать 212 | SFX Y слать шлёшь слать 213 | SFX Y слать шлёте слать 214 | SFX Y слать шлёт слать 215 | SFX Y слать шлём слать 216 | SFX Y скаться щутся скаться 217 | SFX Y скаться щусь скаться 218 | SFX Y скаться щешься скаться 219 | SFX Y скаться щется скаться 220 | SFX Y скаться щетесь скаться 221 | SFX Y скаться щемся скаться 222 | SFX Y скать щут скать 223 | SFX Y скать щу скать 224 | SFX Y скать щешь скать 225 | SFX Y скать щете скать 226 | SFX Y скать щет скать 227 | SFX Y скать щем скать 228 | SFX Y сеть шу сеть 229 | SFX Y саться шутся [^о]саться 230 | SFX Y саться шусь [^о]саться 231 | SFX Y саться шешься [^о]саться 232 | SFX Y саться шется [^о]саться 233 | SFX Y саться шетесь [^о]саться 234 | SFX Y саться шемся [^о]саться 235 | SFX Y сать шут [^о]сать 236 | SFX Y сать шу [^о]сать 237 | SFX Y сать шешь [^о]сать 238 | SFX Y сать шете [^о]сать 239 | SFX Y сать шет [^о]сать 240 | SFX Y сать шем [^о]сать 241 | SFX Y раться рутся [^бд]раться 242 | SFX Y раться русь [^бд]раться 243 | SFX Y раться решься [^бд]раться 244 | SFX Y раться рется [^бд]раться 245 | SFX Y раться ретесь [^бд]раться 246 | SFX Y раться ремся [^бд]раться 247 | SFX Y раться рёшься [^бд]раться 248 | SFX Y раться рётся [^бд]раться 249 | SFX Y раться рётесь [^бд]раться 250 | SFX Y раться рёмся [^бд]раться 251 | SFX Y раться ерутся [бд]раться 252 | SFX Y раться ерусь [бд]раться 253 | SFX Y раться ерешься [бд]раться 254 | SFX Y раться ерется [бд]раться 255 | SFX Y раться еретесь [бд]раться 256 | SFX Y раться еремся [бд]раться 257 | SFX Y раться ерёшься [бд]раться 258 | SFX Y раться ерётся [бд]раться 259 | SFX Y раться ерётесь [бд]раться 260 | SFX Y раться ерёмся [бд]раться 261 | SFX Y рать рут [^бд]рать 262 | SFX Y рать ру [^бд]рать 263 | SFX Y рать решь [^бд]рать 264 | SFX Y рать рете [^бд]рать 265 | SFX Y рать рет [^бд]рать 266 | SFX Y рать рем [^бд]рать 267 | SFX Y рать рёшь [^бд]рать 268 | SFX Y рать рёте [^бд]рать 269 | SFX Y рать рёт [^бд]рать 270 | SFX Y рать рём [^бд]рать 271 | SFX Y рать ерут [бд]рать 272 | SFX Y рать еру [бд]рать 273 | SFX Y рать ерешь [бд]рать 274 | SFX Y рать ерете [бд]рать 275 | SFX Y рать ерет [бд]рать 276 | SFX Y рать ерем [бд]рать 277 | SFX Y рать ерёшь [бд]рать 278 | SFX Y рать ерёте [бд]рать 279 | SFX Y рать ерёт [бд]рать 280 | SFX Y рать ерём [бд]рать 281 | SFX Y яться нутся мяться 282 | SFX Y яться нусь мяться 283 | SFX Y яться нешься мяться 284 | SFX Y яться нется мяться 285 | SFX Y яться нетесь мяться 286 | SFX Y яться немся мяться 287 | SFX Y яться нёшься мяться 288 | SFX Y яться нётся мяться 289 | SFX Y яться нётесь мяться 290 | SFX Y яться нёмся мяться 291 | SFX Y ять нут мять 292 | SFX Y ять ну мять 293 | SFX Y ять нешь мять 294 | SFX Y ять нете мять 295 | SFX Y ять нет мять 296 | SFX Y ять нем мять 297 | SFX Y ять нёшь мять 298 | SFX Y ять нёте мять 299 | SFX Y ять нёт мять 300 | SFX Y ять нём мять 301 | SFX Y наться онятся гнаться 302 | SFX Y наться онишься гнаться 303 | SFX Y наться онится гнаться 304 | SFX Y наться онитесь гнаться 305 | SFX Y наться онимся гнаться 306 | SFX Y наться онюсь гнаться 307 | SFX Y нать онят гнать 308 | SFX Y нать онишь гнать 309 | SFX Y нать оните гнать 310 | SFX Y нать онит гнать 311 | SFX Y нать оним гнать 312 | SFX Y нать оню гнать 313 | SFX Y каться чутся [^с]каться 314 | SFX Y каться чусь [^с]каться 315 | SFX Y каться чешься [^с]каться 316 | SFX Y каться чется [^с]каться 317 | SFX Y каться четесь [^с]каться 318 | SFX Y каться чемся [^с]каться 319 | SFX Y кать чут [^с]кать 320 | SFX Y кать чу [^с]кать 321 | SFX Y кать чешь [^с]кать 322 | SFX Y кать чете [^с]кать 323 | SFX Y кать чет [^с]кать 324 | SFX Y кать чем [^с]кать 325 | SFX Y ить ешь лить 326 | SFX Y ить ете лить 327 | SFX Y ить ет лить 328 | SFX Y ить ем лить 329 | SFX Y ить ют лить 330 | SFX Y ить ю лить 331 | SFX Y и ут расти 332 | SFX Y и у расти 333 | SFX Y и ешь расти 334 | SFX Y и ете расти 335 | SFX Y и ет расти 336 | SFX Y и ем расти 337 | SFX Y и ёшь расти 338 | SFX Y и ёте расти 339 | SFX Y и ёт расти 340 | SFX Y и ём расти 341 | SFX Y хаться шутся хаться 342 | SFX Y хаться шусь хаться 343 | SFX Y хаться шешься хаться 344 | SFX Y хаться шется хаться 345 | SFX Y хаться шетесь хаться 346 | SFX Y хаться шемся хаться 347 | SFX Y хать шут хать 348 | SFX Y хать шу хать 349 | SFX Y хать шешь хать 350 | SFX Y хать шете хать 351 | SFX Y хать шет хать 352 | SFX Y хать шем хать 353 | SFX Y еться ятся [дрт]еться 354 | SFX Y еться люсь петься 355 | SFX Y еться ишься [дрт]еться 356 | SFX Y еться ится [дрт]еться 357 | SFX Y еться итесь [дрт]еться 358 | SFX Y еться имся [дрт]еться 359 | SFX Y еться юсь реться 360 | SFX Y еть ят [дмнпрст]еть 361 | SFX Y еть лю петь 362 | SFX Y еть ишь [дмнпрст]еть 363 | SFX Y еть ите [дмнпрст]еть 364 | SFX Y еть ит [дмнпрст]еть 365 | SFX Y еть им [дмнпрст]еть 366 | SFX Y еть ю реть 367 | SFX Y есть тут честь 368 | SFX Y есть ту честь 369 | SFX Y есть тешь честь 370 | SFX Y есть тете честь 371 | SFX Y есть тет честь 372 | SFX Y есть тем честь 373 | SFX Y есть тёшь честь 374 | SFX Y есть тёте честь 375 | SFX Y есть тёт честь 376 | SFX Y есть тём честь 377 | SFX Y есть ядут сесть 378 | SFX Y есть яду сесть 379 | SFX Y есть ядешь сесть 380 | SFX Y есть ядете сесть 381 | SFX Y есть ядет сесть 382 | SFX Y есть ядем сесть 383 | SFX Y деться жусь деться 384 | SFX Y деть жу деть 385 | SFX Y аться утся рваться 386 | SFX Y аться утся осаться 387 | SFX Y аться усь рваться 388 | SFX Y аться усь осаться 389 | SFX Y аться ятся спаться 390 | SFX Y аться люсь спаться 391 | SFX Y аться ишься жаться 392 | SFX Y аться ишься спаться 393 | SFX Y аться ится жаться 394 | SFX Y аться ится спаться 395 | SFX Y аться итесь жаться 396 | SFX Y аться итесь спаться 397 | SFX Y аться имся жаться 398 | SFX Y аться имся спаться 399 | SFX Y аться ешься рваться 400 | SFX Y аться ешься осаться 401 | SFX Y аться ется рваться 402 | SFX Y аться ется осаться 403 | SFX Y аться етесь рваться 404 | SFX Y аться етесь осаться 405 | SFX Y аться емся рваться 406 | SFX Y аться емся осаться 407 | SFX Y аться ёшься рваться 408 | SFX Y аться ёшься осаться 409 | SFX Y аться ётся рваться 410 | SFX Y аться ётся осаться 411 | SFX Y аться ётесь рваться 412 | SFX Y аться ётесь осаться 413 | SFX Y аться ёмся рваться 414 | SFX Y аться ёмся осаться 415 | SFX Y ать ут рвать 416 | SFX Y ать ут осать 417 | SFX Y ать у рвать 418 | SFX Y ать у осать 419 | SFX Y ать ят спать 420 | SFX Y ать лю спать 421 | SFX Y ать ишь жать 422 | SFX Y ать ишь спать 423 | SFX Y ать ите жать 424 | SFX Y ать ите спать 425 | SFX Y ать ит жать 426 | SFX Y ать ит спать 427 | SFX Y ать им жать 428 | SFX Y ать им спать 429 | SFX Y ать ешь рвать 430 | SFX Y ать ешь осать 431 | SFX Y ать ете рвать 432 | SFX Y ать ете осать 433 | SFX Y ать ет рвать 434 | SFX Y ать ет осать 435 | SFX Y ать ем рвать 436 | SFX Y ать ем осать 437 | SFX Y ать ёшь рвать 438 | SFX Y ать ёшь осать 439 | SFX Y ать ёте рвать 440 | SFX Y ать ёте осать 441 | SFX Y ать ёт рвать 442 | SFX Y ать ёт осать 443 | SFX Y ать ём рвать 444 | SFX Y ать ём осать 445 | 446 | SFX X Y 3 447 | SFX X ый ы нный 448 | SFX X ый о нный 449 | SFX X ый а нный 450 | 451 | SFX W Y 28 452 | SFX W зиться жусь зиться 453 | SFX W зить жу зить 454 | SFX W ься ся иться 455 | SFX W ься есь иться 456 | SFX W ь е ить 457 | SFX W ться шься иться 458 | SFX W ться мся иться 459 | SFX W ть шь ить 460 | SFX W ть т ить 461 | SFX W ть м ить 462 | SFX W титься чусь [^юаеиоясуыэч]титься 463 | SFX W тить чу [^юаеиоясуыэч]тить 464 | SFX W ститься щусь ститься 465 | SFX W стить щу стить 466 | SFX W ситься шусь ситься 467 | SFX W сить шу сить 468 | SFX W иться усь [жшщч]иться 469 | SFX W иться ятся [^жшщч]иться 470 | SFX W иться люсь [бфмпв]иться 471 | SFX W иться атся [жшщч]иться 472 | SFX W иться юсь [аелнору]иться 473 | SFX W ить у [жшщч]ить 474 | SFX W ить ят [^жшщч]ить 475 | SFX W ить лю [бфмпв]ить 476 | SFX W ить ат [жшщч]ить 477 | SFX W ить ю [аелнору]ить 478 | SFX W диться жусь диться 479 | SFX W дить жу дить 480 | 481 | SFX V Y 179 482 | SFX V ться вутся житься 483 | SFX V ться вусь житься 484 | SFX V ться вешься житься 485 | SFX V ться вется житься 486 | SFX V ться ветесь житься 487 | SFX V ться вемся житься 488 | SFX V ться вёшься житься 489 | SFX V ться вётся житься 490 | SFX V ться вётесь житься 491 | SFX V ться вёмся житься 492 | SFX V ться нутся деться 493 | SFX V ться нусь деться 494 | SFX V ться нешься деться 495 | SFX V ться нется деться 496 | SFX V ться нетесь деться 497 | SFX V ться немся деться 498 | SFX V ться ешься уться 499 | SFX V ться ется уться 500 | SFX V ться етесь уться 501 | SFX V ться емся уться 502 | SFX V ться ются уться 503 | SFX V ться юсь уться 504 | SFX V ть вут жить 505 | SFX V ть ву жить 506 | SFX V ть вешь жить 507 | SFX V ть вете жить 508 | SFX V ть вет жить 509 | SFX V ть вем жить 510 | SFX V ть вёшь жить 511 | SFX V ть вёте жить 512 | SFX V ть вёт жить 513 | SFX V ть вём жить 514 | SFX V ть нут деть 515 | SFX V ть ну деть 516 | SFX V ть нешь деть 517 | SFX V ть нете деть 518 | SFX V ть нет деть 519 | SFX V ть нем деть 520 | SFX V ть ешь уть 521 | SFX V ть ете уть 522 | SFX V ть ет уть 523 | SFX V ть ем уть 524 | SFX V ть ют уть 525 | SFX V ть ю уть 526 | SFX V яться ешься яться 527 | SFX V яться ется яться 528 | SFX V яться етесь яться 529 | SFX V яться емся яться 530 | SFX V яться ются яться 531 | SFX V яться юсь яться 532 | SFX V яться ёшься яться 533 | SFX V яться ётся яться 534 | SFX V яться ётесь яться 535 | SFX V яться ёмся яться 536 | SFX V ять ешь ять 537 | SFX V ять ете ять 538 | SFX V ять ет ять 539 | SFX V ять ем ять 540 | SFX V ять ют ять 541 | SFX V ять ю ять 542 | SFX V ять ёшь ять 543 | SFX V ять ёте ять 544 | SFX V ять ёт ять 545 | SFX V ять ём ять 546 | SFX V оваться уешься оваться 547 | SFX V оваться уется оваться 548 | SFX V оваться уетесь оваться 549 | SFX V оваться уемся оваться 550 | SFX V оваться уются оваться 551 | SFX V оваться уюсь оваться 552 | SFX V оваться уёшься оваться 553 | SFX V оваться уётся оваться 554 | SFX V оваться уётесь оваться 555 | SFX V оваться уёмся оваться 556 | SFX V овать уешь овать 557 | SFX V овать уете овать 558 | SFX V овать ует овать 559 | SFX V овать уем овать 560 | SFX V овать уют овать 561 | SFX V овать ую овать 562 | SFX V овать уёшь овать 563 | SFX V овать уёте овать 564 | SFX V овать уёт овать 565 | SFX V овать уём овать 566 | SFX V иться ьешься [блпв]иться 567 | SFX V иться ьется [блпв]иться 568 | SFX V иться ьетесь [блпв]иться 569 | SFX V иться ьемся [блпв]иться 570 | SFX V иться ьются [блпв]иться 571 | SFX V иться ьюсь [блпв]иться 572 | SFX V иться ьёшься [блпв]иться 573 | SFX V иться ьётся [блпв]иться 574 | SFX V иться ьётесь [блпв]иться 575 | SFX V иться ьёмся [блпв]иться 576 | SFX V ить ьешь [блпв]ить 577 | SFX V ить ьете [блпв]ить 578 | SFX V ить ьет [блпв]ить 579 | SFX V ить ьем [блпв]ить 580 | SFX V ить ьют [блпв]ить 581 | SFX V ить ью [блпв]ить 582 | SFX V ить ьёшь [блпв]ить 583 | SFX V ить ьёте [блпв]ить 584 | SFX V ить ьёт [блпв]ить 585 | SFX V ить ьём [блпв]ить 586 | SFX V хаться дутся хаться 587 | SFX V хаться дусь хаться 588 | SFX V хаться дешься хаться 589 | SFX V хаться дется хаться 590 | SFX V хаться детесь хаться 591 | SFX V хаться демся хаться 592 | SFX V хать дут хать 593 | SFX V хать ду хать 594 | SFX V хать дешь хать 595 | SFX V хать дете хать 596 | SFX V хать дет хать 597 | SFX V хать дем хать 598 | SFX V ечься яжешься лечься 599 | SFX V ечься яжется лечься 600 | SFX V ечься яжетесь лечься 601 | SFX V ечься яжемся лечься 602 | SFX V ечься ягутся лечься 603 | SFX V ечься ягусь лечься 604 | SFX V ечь яжешь лечь 605 | SFX V ечь яжете лечь 606 | SFX V ечь яжет лечь 607 | SFX V ечь яжем лечь 608 | SFX V ечь ягут лечь 609 | SFX V ечь ягу лечь 610 | SFX V еваться уется [цжшщч]еваться 611 | SFX V еваться уются [цжшщч]еваться 612 | SFX V еваться уётся [цжшщч]еваться 613 | SFX V еваться юешься [^цжшщч]еваться 614 | SFX V еваться юется [^цжшщч]еваться 615 | SFX V еваться юетесь [^цжшщч]еваться 616 | SFX V еваться юемся [^цжшщч]еваться 617 | SFX V еваться юются [^цжшщч]еваться 618 | SFX V еваться ююсь [^цжшщч]еваться 619 | SFX V еваться юёшься [^цжшщч]еваться 620 | SFX V еваться юётся [^цжшщч]еваться 621 | SFX V еваться юётесь [^цжшщч]еваться 622 | SFX V еваться юёмся [^цжшщч]еваться 623 | SFX V евать уешь [цжшщч]евать 624 | SFX V евать уете [цжшщч]евать 625 | SFX V евать ует [цжшщч]евать 626 | SFX V евать уем [цжшщч]евать 627 | SFX V евать уют [цжшщч]евать 628 | SFX V евать ую [цжшщч]евать 629 | SFX V евать уёшь [цжшщч]евать 630 | SFX V евать уёте [цжшщч]евать 631 | SFX V евать уёт [цжшщч]евать 632 | SFX V евать уём [цжшщч]евать 633 | SFX V евать юешь [^цжшщч]евать 634 | SFX V евать юете [^цжшщч]евать 635 | SFX V евать юет [^цжшщч]евать 636 | SFX V евать юем [^цжшщч]евать 637 | SFX V евать юют [^цжшщч]евать 638 | SFX V евать юю [^цжшщч]евать 639 | SFX V евать юёшь [^цжшщч]евать 640 | SFX V евать юёте [^цжшщч]евать 641 | SFX V евать юёт [^цжшщч]евать 642 | SFX V евать юём [^цжшщч]евать 643 | SFX V аться лешься паться 644 | SFX V аться лется паться 645 | SFX V аться летесь паться 646 | SFX V аться лемся паться 647 | SFX V аться лются паться 648 | SFX V аться люсь паться 649 | SFX V ать ут дать 650 | SFX V ать у дать 651 | SFX V ать лешь пать 652 | SFX V ать лете пать 653 | SFX V ать лет пать 654 | SFX V ать лем пать 655 | SFX V ать лют пать 656 | SFX V ать лю пать 657 | SFX V ать ешь дать 658 | SFX V ать ете дать 659 | SFX V ать ет дать 660 | SFX V ать ем дать 661 | 662 | SFX U Y 162 663 | SFX U чься жешься чься 664 | SFX U чься жется чься 665 | SFX U чься жетесь чься 666 | SFX U чься жемся чься 667 | SFX U чься жёшься чься 668 | SFX U чься жётся чься 669 | SFX U чься жётесь чься 670 | SFX U чься жёмся чься 671 | SFX U чься гутся чься 672 | SFX U чься гусь чься 673 | SFX U чь жешь чь 674 | SFX U чь жете чь 675 | SFX U чь жет чь 676 | SFX U чь жем чь 677 | SFX U чь жёшь чь 678 | SFX U чь жёте чь 679 | SFX U чь жёт чь 680 | SFX U чь жём чь 681 | SFX U чь гут чь 682 | SFX U чь гу чь 683 | SFX U ься ся уться 684 | SFX U ься ся ояться 685 | SFX U ься ся [жшщч]аться 686 | SFX U ваться ешься аваться 687 | SFX U ваться ется аваться 688 | SFX U ваться етесь аваться 689 | SFX U ваться емся аваться 690 | SFX U ваться ются аваться 691 | SFX U ваться юсь аваться 692 | SFX U ваться ёшься аваться 693 | SFX U ваться ётся аваться 694 | SFX U ваться ётесь аваться 695 | SFX U ваться ёмся аваться 696 | SFX U вать ешь авать 697 | SFX U вать ете авать 698 | SFX U вать ет авать 699 | SFX U вать ем авать 700 | SFX U вать ют авать 701 | SFX U вать ю авать 702 | SFX U вать ёшь авать 703 | SFX U вать ёте авать 704 | SFX U вать ёт авать 705 | SFX U вать ём авать 706 | SFX U уться ешься уться 707 | SFX U уться ется уться 708 | SFX U уться етесь уться 709 | SFX U уться емся уться 710 | SFX U уться ёшься уться 711 | SFX U уться ётся уться 712 | SFX U уться ётесь уться 713 | SFX U уться ёмся уться 714 | SFX U уть у уть 715 | SFX U уть ешь уть 716 | SFX U уть ете уть 717 | SFX U уть ет уть 718 | SFX U уть ем уть 719 | SFX U уть ёшь уть 720 | SFX U уть ёте уть 721 | SFX U уть ёт уть 722 | SFX U уть ём уть 723 | SFX U ться сь уться 724 | SFX U ться ешься [^аеоу]яться 725 | SFX U ться ется [^аеоу]яться 726 | SFX U ться етесь [^аеоу]яться 727 | SFX U ться емся [^аеоу]яться 728 | SFX U ться ются [^аеоу]яться 729 | SFX U ться юсь [^аеоу]яться 730 | SFX U ть т уть 731 | SFX U ть т оять 732 | SFX U ть т [жшщч]ать 733 | SFX U ть ешь [^аеоу]ять 734 | SFX U ть ете [^аеоу]ять 735 | SFX U ть ет [^аеоу]ять 736 | SFX U ть ем [^аеоу]ять 737 | SFX U ть ют [^аеоу]ять 738 | SFX U ть ю [^аеоу]ять 739 | SFX U яться ишься ояться 740 | SFX U яться ится ояться 741 | SFX U яться итесь ояться 742 | SFX U яться имся ояться 743 | SFX U яться ешься [аеу]яться 744 | SFX U яться ется [аеу]яться 745 | SFX U яться етесь [аеу]яться 746 | SFX U яться емся [аеу]яться 747 | SFX U яться ются [аеу]яться 748 | SFX U яться юсь [аеоу]яться 749 | SFX U ять ишь оять 750 | SFX U ять ите оять 751 | SFX U ять ит оять 752 | SFX U ять им оять 753 | SFX U ять ешь [аеу]ять 754 | SFX U ять ете [аеу]ять 755 | SFX U ять ет [аеу]ять 756 | SFX U ять ем [аеу]ять 757 | SFX U ять ют [аеу]ять 758 | SFX U ять ю [аеоу]ять 759 | SFX U оваться уешься оваться 760 | SFX U оваться уется оваться 761 | SFX U оваться уетесь оваться 762 | SFX U оваться уемся оваться 763 | SFX U оваться уются оваться 764 | SFX U оваться уюсь оваться 765 | SFX U овать уешь овать 766 | SFX U овать уете овать 767 | SFX U овать ует овать 768 | SFX U овать уем овать 769 | SFX U овать уют овать 770 | SFX U овать ую овать 771 | SFX U еваться уешься [цжшщч]еваться 772 | SFX U еваться уется [цжшщч]еваться 773 | SFX U еваться уетесь [цжшщч]еваться 774 | SFX U еваться уемся [цжшщч]еваться 775 | SFX U еваться уются [цжшщч]еваться 776 | SFX U еваться уюсь [цжшщч]еваться 777 | SFX U еваться юешься [^цжшщч]еваться 778 | SFX U еваться юется [^цжшщч]еваться 779 | SFX U еваться юетесь [^цжшщч]еваться 780 | SFX U еваться юемся [^цжшщч]еваться 781 | SFX U еваться юются [^цжшщч]еваться 782 | SFX U еваться ююсь [^цжшщч]еваться 783 | SFX U евать уешь [цжшщч]евать 784 | SFX U евать уете [цжшщч]евать 785 | SFX U евать ует [цжшщч]евать 786 | SFX U евать уем [цжшщч]евать 787 | SFX U евать уют [цжшщч]евать 788 | SFX U евать ую [цжшщч]евать 789 | SFX U евать юешь [^цжшщч]евать 790 | SFX U евать юете [^цжшщч]евать 791 | SFX U евать юет [^цжшщч]евать 792 | SFX U евать юем [^цжшщч]евать 793 | SFX U евать юют [^цжшщч]евать 794 | SFX U евать юю [^цжшщч]евать 795 | SFX U аться утся даться 796 | SFX U аться усь даться 797 | SFX U аться усь [жшщч]аться 798 | SFX U аться ишься [жшщч]аться 799 | SFX U аться ится [жшщч]аться 800 | SFX U аться итесь [жшщч]аться 801 | SFX U аться имся [жшщч]аться 802 | SFX U аться ешься даться 803 | SFX U аться ется даться 804 | SFX U аться етесь даться 805 | SFX U аться емся даться 806 | SFX U аться ёшься даться 807 | SFX U аться ётся даться 808 | SFX U аться ётесь даться 809 | SFX U аться ёмся даться 810 | SFX U ать ут дать 811 | SFX U ать у дать 812 | SFX U ать у [жшщч]ать 813 | SFX U ать ишь [жшщч]ать 814 | SFX U ать ите [жшщч]ать 815 | SFX U ать ит [жшщч]ать 816 | SFX U ать им [жшщч]ать 817 | SFX U ать ешь дать 818 | SFX U ать ете дать 819 | SFX U ать ет дать 820 | SFX U ать ем дать 821 | SFX U ать ёшь дать 822 | SFX U ать ёте дать 823 | SFX U ать ёт дать 824 | SFX U ать ём дать 825 | 826 | SFX T Y 38 827 | SFX T уться ьтесь уться 828 | SFX T уться ься уться 829 | SFX T уть ьте уть 830 | SFX T уть ь уть 831 | SFX T саться шитесь саться 832 | SFX T саться шись саться 833 | SFX T сать шите сать 834 | SFX T сать ши сать 835 | SFX T яться йтесь [аеоу]яться 836 | SFX T яться йся [аеоу]яться 837 | SFX T ять йте [аеоу]ять 838 | SFX T ять й [аеоу]ять 839 | SFX T оваться уйтесь оваться 840 | SFX T оваться уйся оваться 841 | SFX T овать уйте овать 842 | SFX T овать уй овать 843 | SFX T иться ьтесь [^аео]иться 844 | SFX T иться ься [^аео]иться 845 | SFX T иться йтесь [аео]иться 846 | SFX T иться йся [аео]иться 847 | SFX T ить ьте [^аео]ить 848 | SFX T ить ь [^аео]ить 849 | SFX T ить йте [аео]ить 850 | SFX T ить й [аео]ить 851 | SFX T еваться уйтесь [цжшщч]еваться 852 | SFX T еваться уйся [цжшщч]еваться 853 | SFX T еваться юйтесь [^цжшщч]еваться 854 | SFX T еваться юйся [^цжшщч]еваться 855 | SFX T евать уйте [цжшщч]евать 856 | SFX T евать уй [цжшщч]евать 857 | SFX T евать юйте [^цжшщч]евать 858 | SFX T евать юй [^цжшщч]евать 859 | SFX T еться итесь еться 860 | SFX T еться ись еться 861 | SFX T еть ите еть 862 | SFX T еть и еть 863 | SFX T аться ись [жч]аться 864 | SFX T ать и [жч]ать 865 | 866 | SFX S Y 40 867 | SFX S ый ы [^н]ый 868 | SFX S ый о [^н]ый 869 | SFX S ый а [^н]ый 870 | SFX S ый 0 [^н]ый 871 | SFX S ьный ен ьный 872 | SFX S ький ек ький 873 | SFX S ой ы [^гх]ой 874 | SFX S ой о ой 875 | SFX S ой и [гх]ой 876 | SFX S ой а ой 877 | SFX S ой 0 ой 878 | SFX S ный ы нный 879 | SFX S ный ы [^ё]нный 880 | SFX S ный он лный 881 | SFX S ный о нный 882 | SFX S ный о [^ё]нный 883 | SFX S ный ны [^н]ный 884 | SFX S ный но [^н]ный 885 | SFX S ный на [^н]ный 886 | SFX S ный н еный 887 | SFX S ный н [ёе]ный 888 | SFX S ный ен [^ейлнь]ный 889 | SFX S ный ен [^ёейлнь]ный 890 | SFX S ный а нный 891 | SFX S ный а [^ё]нный 892 | SFX S нный н нный 893 | SFX S кий ок [^аеийоуьы]кий 894 | SFX S кий ок [^ёаеийоуьы]кий 895 | SFX S кий к [аеиоуы]кий 896 | SFX S кий к [ёаеиоуы]кий 897 | SFX S йный ен йный 898 | SFX S йкий ек йкий 899 | SFX S ий о [гхк]ий 900 | SFX S ий и [гхкжщч]ий 901 | SFX S ий е [жщч]ий 902 | SFX S ий а [гхкжщч]ий 903 | SFX S ий 0 [гхжщч]ий 904 | SFX S ённый ены ённый 905 | SFX S ённый ено ённый 906 | SFX S ённый ена ённый 907 | 908 | SFX R Y 4 909 | SFX R ться вшись [аеиояуы]ться 910 | SFX R ть в [аеиояуы]ть 911 | SFX R сться вшись сться 912 | SFX R сть в сть 913 | 914 | SFX Q Y 6 915 | SFX Q оваться уясь оваться 916 | SFX Q овать уя овать 917 | SFX Q еваться уясь [цжшщч]еваться 918 | SFX Q еваться юясь [^цжшщч]еваться 919 | SFX Q евать уя [цжшщч]евать 920 | SFX Q евать юя [^цжшщч]евать 921 | 922 | SFX P Y 12 923 | SFX P ыться оясь ыться 924 | SFX P ыть оя ыть 925 | SFX P ться сь [аеоу]яться 926 | SFX P ться ясь [ае]ться 927 | SFX P ться ясь [^аеоу]яться 928 | SFX P ть я [ае]ть 929 | SFX P ть я [^аеоу]ять 930 | SFX P ять я [аеоу]ять 931 | SFX P иться ясь [^жшщч]иться 932 | SFX P иться ась [жшщч]иться 933 | SFX P ить я [^жшщч]ить 934 | SFX P ить а [жшщч]ить 935 | 936 | SFX O Y 131 937 | SFX O ы ами ы 938 | SFX O ы ам ы 939 | SFX O ы ах ы 940 | SFX O рин р рин 941 | SFX O оть тями оть 942 | SFX O оть тям оть 943 | SFX O оть тях оть 944 | SFX O оть тя оть 945 | SFX O оть ти оть 946 | SFX O оть тем оть 947 | SFX O оть тей оть 948 | SFX O оть те оть 949 | SFX O оть тю оть 950 | SFX O ок ку ок 951 | SFX O ок ков ок 952 | SFX O ок ком ок 953 | SFX O ок ки ок 954 | SFX O ок ке ок 955 | SFX O ок ками ок 956 | SFX O ок кам ок 957 | SFX O ок ках ок 958 | SFX O ок ка ок 959 | SFX O нин н нин 960 | SFX O ин ы рин 961 | SFX O ин е нин 962 | SFX O ин ами ин 963 | SFX O ин ам ин 964 | SFX O ин ах ин 965 | SFX O ий ья ий 966 | SFX O ий ьими ий 967 | SFX O ий ьим ий 968 | SFX O ий ьих ий 969 | SFX O ий ьи ий 970 | SFX O ий ьему ий 971 | SFX O ий ьем ий 972 | SFX O ий ьей ий 973 | SFX O ий ьего ий 974 | SFX O ий ье ий 975 | SFX O ий ью ий 976 | SFX O и ями [арс]ти 977 | SFX O и ями [абеилнорсь]и 978 | SFX O и ям [абдеилнорсть]и 979 | SFX O и ях [абдеилнорсть]и 980 | SFX O и ами [^абдеилнорсть]и 981 | SFX O и ам [^абдеилнорсть]и 982 | SFX O и ах [^абдеилнорсть]и 983 | SFX O ень нями ень 984 | SFX O ень ням ень 985 | SFX O ень нях ень 986 | SFX O ень ня ень 987 | SFX O ень ни ень 988 | SFX O ень нем ень 989 | SFX O ень ней ень 990 | SFX O ень не ень 991 | SFX O ень ню ень 992 | SFX O ел лы ел 993 | SFX O ел лу ел 994 | SFX O ел лов ел 995 | SFX O ел лом ел 996 | SFX O ел ле ел 997 | SFX O ел лами ел 998 | SFX O ел лам ел 999 | SFX O ел лах ел 1000 | SFX O ел ла ел 1001 | SFX O ек ьку [лнрс]ек 1002 | SFX O ек ьков [лнрс]ек 1003 | SFX O ек ьком [лнрс]ек 1004 | SFX O ек ьки [лнрс]ек 1005 | SFX O ек ьке [лнрс]ек 1006 | SFX O ек ьками [лнрс]ек 1007 | SFX O ек ькам [лнрс]ек 1008 | SFX O ек ьках [лнрс]ек 1009 | SFX O ек ька [лнрс]ек 1010 | SFX O ек ку [жшч]ек 1011 | SFX O ек ков [жшч]ек 1012 | SFX O ек ком [жшч]ек 1013 | SFX O ек ки [жшч]ек 1014 | SFX O ек ке [жшч]ек 1015 | SFX O ек ками [жшч]ек 1016 | SFX O ек кам [жшч]ек 1017 | SFX O ек ках [жшч]ек 1018 | SFX O ек ка [жшч]ек 1019 | SFX O ец ьцы лец 1020 | SFX O ец ьцу лец 1021 | SFX O ец ьце лец 1022 | SFX O ец ьцами лец 1023 | SFX O ец ьцам лец 1024 | SFX O ец ьцах лец 1025 | SFX O ец ьца лец 1026 | SFX O ец йцы [аеио]ец 1027 | SFX O ец йцу [аеио]ец 1028 | SFX O ец йцев [аеи]ец 1029 | SFX O ец йцем [аеи]ец 1030 | SFX O ец йце [аеио]ец 1031 | SFX O ец йцами [аеио]ец 1032 | SFX O ец йцам [аеио]ец 1033 | SFX O ец йцах [аеио]ец 1034 | SFX O ец йца [аеио]ец 1035 | SFX O ец цы [^аеило]ец 1036 | SFX O ец цу [^аеило]ец 1037 | SFX O ец це [^аеило]ец 1038 | SFX O ец цами [^аеило]ец 1039 | SFX O ец цам [^аеило]ец 1040 | SFX O ец цах [^аеило]ец 1041 | SFX O ец ца [^аеило]ец 1042 | SFX O ёл лы ёл 1043 | SFX O ёл лу ёл 1044 | SFX O ёл лов ёл 1045 | SFX O ёл лом ёл 1046 | SFX O ёл ле ёл 1047 | SFX O ёл лами ёл 1048 | SFX O ёл лам ёл 1049 | SFX O ёл лах ёл 1050 | SFX O ёл ла ёл 1051 | SFX O ёк ьку [лнрс]ёк 1052 | SFX O ёк ьков [лнрс]ёк 1053 | SFX O ёк ьком [лнрс]ёк 1054 | SFX O ёк ьки [лнрс]ёк 1055 | SFX O ёк ьке [лнрс]ёк 1056 | SFX O ёк ьками [лнрс]ёк 1057 | SFX O ёк ькам [лнрс]ёк 1058 | SFX O ёк ьках [лнрс]ёк 1059 | SFX O ёк ька [лнрс]ёк 1060 | SFX O 0 у ин 1061 | SFX O 0 ом ин 1062 | SFX O 0 ми [ая] 1063 | SFX O 0 м [ая] 1064 | SFX O 0 х [ая] 1065 | SFX O 0 ев [аняр]ц 1066 | SFX O 0 е ин 1067 | SFX O 0 а ин 1068 | 1069 | SFX N Y 17 1070 | SFX N ь ями [^жшщч]ь 1071 | SFX N ь ям [^жшщч]ь 1072 | SFX N ь ях [^жшщч]ь 1073 | SFX N ь и ь 1074 | SFX N ь ей ь 1075 | SFX N ь ами [жшщч]ь 1076 | SFX N ь ам [жшщч]ь 1077 | SFX N ь ах [жшщч]ь 1078 | SFX N 0 у [^ь] 1079 | SFX N 0 ов [^цжьшщч] 1080 | SFX N 0 ом [^цжьшщч] 1081 | SFX N 0 е [^ь] 1082 | SFX N 0 ами [^ь] 1083 | SFX N 0 ам [^ь] 1084 | SFX N 0 ах [^ь] 1085 | SFX N 0 а [^ь] 1086 | SFX N 0 ю ь 1087 | 1088 | SFX M Y 108 1089 | SFX M чься кутся чься 1090 | SFX M чься кусь чься 1091 | SFX M чь кут чь 1092 | SFX M чь ку чь 1093 | SFX M ыться оешься ыться 1094 | SFX M ыться оется ыться 1095 | SFX M ыться оетесь ыться 1096 | SFX M ыться оемся ыться 1097 | SFX M ыться оются ыться 1098 | SFX M ыться оюсь ыться 1099 | SFX M ыть оешь ыть 1100 | SFX M ыть оете ыть 1101 | SFX M ыть оет ыть 1102 | SFX M ыть оем ыть 1103 | SFX M ыть оют ыть 1104 | SFX M ыть ою ыть 1105 | SFX M ься ся уться 1106 | SFX M ься ешься чься 1107 | SFX M ься ется чься 1108 | SFX M ься етесь чься 1109 | SFX M ься емся чься 1110 | SFX M ься ёшься чься 1111 | SFX M ься ётся чься 1112 | SFX M ься ётесь чься 1113 | SFX M ься ёмся чься 1114 | SFX M ь ешь чь 1115 | SFX M ь ете чь 1116 | SFX M ь ет чь 1117 | SFX M ь ем чь 1118 | SFX M ь ёшь чь 1119 | SFX M ь ёте чь 1120 | SFX M ь ёт чь 1121 | SFX M ь ём чь 1122 | SFX M уться ешься уться 1123 | SFX M уться ется уться 1124 | SFX M уться етесь уться 1125 | SFX M уться емся уться 1126 | SFX M уть у уть 1127 | SFX M уть ешь уть 1128 | SFX M уть ете уть 1129 | SFX M уть ет уть 1130 | SFX M уть ем уть 1131 | SFX M ться сь уться 1132 | SFX M ться ешься [ае]ться 1133 | SFX M ться ется [ае]ться 1134 | SFX M ться етесь [ае]ться 1135 | SFX M ться емся [ае]ться 1136 | SFX M ться ются [ае]ться 1137 | SFX M ться юсь [ае]ться 1138 | SFX M ть т уть 1139 | SFX M ть ешь [ае]ть 1140 | SFX M ть ете [ае]ть 1141 | SFX M ть ет [ае]ть 1142 | SFX M ть ем [ае]ть 1143 | SFX M ть ют [ае]ть 1144 | SFX M ть ю [ае]ть 1145 | SFX M тись утся [сз]тись 1146 | SFX M тись усь [сз]тись 1147 | SFX M тись ешься [сз]тись 1148 | SFX M тись ется [сз]тись 1149 | SFX M тись етесь [сз]тись 1150 | SFX M тись емся [сз]тись 1151 | SFX M тись дутся йтись 1152 | SFX M тись дусь йтись 1153 | SFX M тись дешься йтись 1154 | SFX M тись дется йтись 1155 | SFX M тись детесь йтись 1156 | SFX M тись демся йтись 1157 | SFX M тись дёшься йтись 1158 | SFX M тись дётся йтись 1159 | SFX M тись дётесь йтись 1160 | SFX M тись дёмся йтись 1161 | SFX M тись ёшься [сз]тись 1162 | SFX M тись ётся [сз]тись 1163 | SFX M тись ётесь [сз]тись 1164 | SFX M тись ёмся [сз]тись 1165 | SFX M ти ут [сз]ти 1166 | SFX M ти у [сз]ти 1167 | SFX M ти ешь [сз]ти 1168 | SFX M ти ете [сз]ти 1169 | SFX M ти ет [сз]ти 1170 | SFX M ти ем [сз]ти 1171 | SFX M ти дут йти 1172 | SFX M ти ду йти 1173 | SFX M ти дешь йти 1174 | SFX M ти дете йти 1175 | SFX M ти дет йти 1176 | SFX M ти дем йти 1177 | SFX M ти дёшь йти 1178 | SFX M ти дёте йти 1179 | SFX M ти дёт йти 1180 | SFX M ти дём йти 1181 | SFX M ти ёшь [сз]ти 1182 | SFX M ти ёте [сз]ти 1183 | SFX M ти ёт [сз]ти 1184 | SFX M ти ём [сз]ти 1185 | SFX M оться ешься оться 1186 | SFX M оться ется оться 1187 | SFX M оться етесь оться 1188 | SFX M оться емся оться 1189 | SFX M оться ются оться 1190 | SFX M оться юсь оться 1191 | SFX M оть ешь оть 1192 | SFX M оть ете оть 1193 | SFX M оть ет оть 1194 | SFX M оть ем оть 1195 | SFX M оть ют оть 1196 | SFX M оть ю оть 1197 | 1198 | SFX L Y 63 1199 | SFX L чься кся чься 1200 | SFX L чься кся [^е]чься 1201 | SFX L чься клось чься 1202 | SFX L чься клись чься 1203 | SFX L чься клась чься 1204 | SFX L чь кло чь 1205 | SFX L чь кли чь 1206 | SFX L чь кла чь 1207 | SFX L чь к чь 1208 | SFX L чь к [^е]чь 1209 | SFX L зть з зть 1210 | SFX L зти з зти 1211 | SFX L ться ся зться 1212 | SFX L ться лся [^сз]ться 1213 | SFX L ться лось [^с]ться 1214 | SFX L ться лись [^с]ться 1215 | SFX L ться лась [^с]ться 1216 | SFX L ть ло [^с]ть 1217 | SFX L ть ли [^с]ть 1218 | SFX L ть ла [^с]ть 1219 | SFX L ть л [^сз]ть 1220 | SFX L ти ло зти 1221 | SFX L ти ли зти 1222 | SFX L ти ла зти 1223 | SFX L сться лся сться 1224 | SFX L сться лось сться 1225 | SFX L сться лись сться 1226 | SFX L сться лась сться 1227 | SFX L сть ло [^ч].сть 1228 | SFX L сть ли [^ч].сть 1229 | SFX L сть ла [^ч].сть 1230 | SFX L сть л [^ч].сть 1231 | SFX L стись лся стись 1232 | SFX L стись лся [^е]стись 1233 | SFX L стись лось стись 1234 | SFX L стись лись стись 1235 | SFX L стись лась стись 1236 | SFX L сти ло сти 1237 | SFX L сти ли сти 1238 | SFX L сти ла сти 1239 | SFX L сти л сти 1240 | SFX L сти л [^е]сти 1241 | SFX L ся лось [^аияь]ся 1242 | SFX L ся лись [^аияь]ся 1243 | SFX L ся лась [^аияь]ся 1244 | SFX L лзти лз лзти 1245 | SFX L ечься ёкся ечься 1246 | SFX L ечь ёк ечь 1247 | SFX L езти ёз езти 1248 | SFX L есть ло честь 1249 | SFX L есть ли честь 1250 | SFX L есть ла честь 1251 | SFX L есть ел честь 1252 | SFX L есть ёл честь 1253 | SFX L естись ёлся естись 1254 | SFX L ести ёл ести 1255 | SFX L ась ось ась 1256 | SFX L ась ись ась 1257 | SFX L а о а 1258 | SFX L а и а 1259 | SFX L 0 ло [^аияь] 1260 | SFX L 0 ли [^аияь] 1261 | SFX L 0 ла [^аияь] 1262 | 1263 | SFX K Y 55 1264 | SFX K ще щ ще 1265 | SFX K ье ий ье 1266 | SFX K ь ями ь 1267 | SFX K ь ям ь 1268 | SFX K ь ях ь 1269 | SFX K ь я ь 1270 | SFX K ь и ь 1271 | SFX K ь ем ь 1272 | SFX K ь ей ь 1273 | SFX K ь е ь 1274 | SFX K ь ю ь 1275 | SFX K о у о 1276 | SFX K о и [ишч]ко 1277 | SFX K о е о 1278 | SFX K о ами о 1279 | SFX K о ам о 1280 | SFX K о ах о 1281 | SFX K о а о 1282 | SFX K о 0 [дгств]о 1283 | SFX K й ями й 1284 | SFX K й ям й 1285 | SFX K й ях й 1286 | SFX K й я й 1287 | SFX K й и ий 1288 | SFX K й и [юаеояу]й 1289 | SFX K й ев й 1290 | SFX K й ем й 1291 | SFX K й е [^и]й 1292 | SFX K й ю й 1293 | SFX K е у [цжшщ]е 1294 | SFX K е ями [^цжшщ]е 1295 | SFX K е ям [^цжшщ]е 1296 | SFX K е ях [^цжшщ]е 1297 | SFX K е я [^цжшщ]е 1298 | SFX K е й ие 1299 | SFX K е и ие 1300 | SFX K е ей [^цижьщ]е 1301 | SFX K е ами [цжшщ]е 1302 | SFX K е ам [цжшщ]е 1303 | SFX K е ах [цжшщ]е 1304 | SFX K е а [цжшщ]е 1305 | SFX K е ю [^цжшщ]е 1306 | SFX K 0 ы [^егхйкожьшщч] 1307 | SFX K 0 у [^ейоь] 1308 | SFX K 0 ов [^цейожьшщч] 1309 | SFX K 0 ом [^цейожьшщч] 1310 | SFX K 0 м о 1311 | SFX K 0 м е 1312 | SFX K 0 и [гхкжшщч] 1313 | SFX K 0 ей [жшщч] 1314 | SFX K 0 е [^ейоь] 1315 | SFX K 0 ами [^ейоь] 1316 | SFX K 0 ам [^ейоь] 1317 | SFX K 0 ах [^ейоь] 1318 | SFX K 0 а [^ейоь] 1319 | 1320 | SFX J Y 37 1321 | SFX J ь я ь 1322 | SFX J ь ем ь 1323 | SFX J ь е ь 1324 | SFX J ь ю ь 1325 | SFX J о у о 1326 | SFX J о е о 1327 | SFX J о а о 1328 | SFX J й я й 1329 | SFX J й и ий 1330 | SFX J й ем й 1331 | SFX J й е [^и]й 1332 | SFX J й ю й 1333 | SFX J е у [цжшщ]е 1334 | SFX J е я [^цжшщ]е 1335 | SFX J е и ие 1336 | SFX J е а [цжшщ]е 1337 | SFX J е ю [^цжшщ]е 1338 | SFX J ёж ежу ёж 1339 | SFX J ёж еже ёж 1340 | SFX J ёж ежа ёж 1341 | SFX J ё я ё 1342 | SFX J ё е ьё 1343 | SFX J ё ю ё 1344 | SFX J 0 у [^ейоь] 1345 | SFX J 0 у [^ёейожь] 1346 | SFX J 0 у [^ё]ж 1347 | SFX J 0 ом [^цейожьшщч] 1348 | SFX J 0 ом [^ёцейожьшщч] 1349 | SFX J 0 м о 1350 | SFX J 0 м е 1351 | SFX J 0 м [ёе] 1352 | SFX J 0 е [^ейоь] 1353 | SFX J 0 е [^ёейожь] 1354 | SFX J 0 е [^ё]ж 1355 | SFX J 0 а [^ейоь] 1356 | SFX J 0 а [^ёейожь] 1357 | SFX J 0 а [^ё]ж 1358 | 1359 | SFX I Y 30 1360 | SFX I ьня ен ьня 1361 | SFX I ька ек ька 1362 | SFX I я ь [аеиояуы]ня 1363 | SFX I я й [еиу]я 1364 | SFX I я и я 1365 | SFX I я ей я 1366 | SFX I я ею я 1367 | SFX I я е [^и]я 1368 | SFX I я ю я 1369 | SFX I ня ен [^аеийояуьыз]ня 1370 | SFX I ка ок [^юацеийояужьышч]ка 1371 | SFX I ка к [юаеиояуы]ка 1372 | SFX I ка ек [цжшч]ка 1373 | SFX I йня ен йня 1374 | SFX I йка ек йка 1375 | SFX I а ы [^гхкжшщч]а 1376 | SFX I а у а 1377 | SFX I а ой [^цжшщч]а 1378 | SFX I а ою [^цжшщч]а 1379 | SFX I а и [гхкжшщч]а 1380 | SFX I а ей [цшщч]а 1381 | SFX I а ею [цшщч]а 1382 | SFX I а е а 1383 | SFX I а 0 [^к]а 1384 | SFX I 0 ми я 1385 | SFX I 0 ми а 1386 | SFX I 0 м я 1387 | SFX I 0 м а 1388 | SFX I 0 х я 1389 | SFX I 0 х а 1390 | 1391 | SFX H Y 14 1392 | SFX H я и я 1393 | SFX H я ей я 1394 | SFX H я ею я 1395 | SFX H я е [^и]я 1396 | SFX H я ю я 1397 | SFX H й ю [ео]й 1398 | SFX H а ы [^гхкжшщч]а 1399 | SFX H а у а 1400 | SFX H а ой [^цжшщч]а 1401 | SFX H а ою [^цжшщч]а 1402 | SFX H а и [гхкжшщч]а 1403 | SFX H а ей ща 1404 | SFX H а ею ща 1405 | SFX H а е а 1406 | 1407 | SFX G Y 52 1408 | SFX G ый ому ый 1409 | SFX G ый ом ый 1410 | SFX G ый ого ый 1411 | SFX G ьня ен ьня 1412 | SFX G ь ями ь 1413 | SFX G ь ям ь 1414 | SFX G ь ях ь 1415 | SFX G ь я ь 1416 | SFX G ь и ь 1417 | SFX G ь ем ь 1418 | SFX G ь ей ь 1419 | SFX G ь е ь 1420 | SFX G ь ю ь 1421 | SFX G ь ём ь 1422 | SFX G я ь [аеиоуы]ня 1423 | SFX G я й [еиу]я 1424 | SFX G я и я 1425 | SFX G я ей я 1426 | SFX G я ею я 1427 | SFX G я е [^и]я 1428 | SFX G я ю я 1429 | SFX G я ёй я 1430 | SFX G я ёю я 1431 | SFX G ок ку ок 1432 | SFX G ок ком ок 1433 | SFX G ок ке ок 1434 | SFX G ок ка ок 1435 | SFX G ой им ой 1436 | SFX G ня ен [^аеийоуьыз]ня 1437 | SFX G йня ен йня 1438 | SFX G й му ой 1439 | SFX G й м ый 1440 | SFX G й м ой 1441 | SFX G й м ий 1442 | SFX G й го ой 1443 | SFX G ий ому ий 1444 | SFX G ий ом ий 1445 | SFX G ий ого ий 1446 | SFX G ек ку ек 1447 | SFX G ек ком ек 1448 | SFX G ек ке ек 1449 | SFX G ек ка ек 1450 | SFX G ец цу ец 1451 | SFX G ец це ец 1452 | SFX G ец ца ец 1453 | SFX G 0 ым [^цейкояжьшщч] 1454 | SFX G 0 у [^цейкояь] 1455 | SFX G 0 ми я 1456 | SFX G 0 м я 1457 | SFX G 0 х я 1458 | SFX G 0 е [^цейкояь] 1459 | SFX G 0 а [^цейкояь] 1460 | 1461 | SFX F Y 25 1462 | SFX F ь и ь 1463 | SFX F онок атами онок 1464 | SFX F онок атам онок 1465 | SFX F онок атах онок 1466 | SFX F онок ата онок 1467 | SFX F онок ат онок 1468 | SFX F ок ку нок 1469 | SFX F ок ком нок 1470 | SFX F ок ке нок 1471 | SFX F ок ка нок 1472 | SFX F енок ятами енок 1473 | SFX F енок ятам енок 1474 | SFX F енок ятах енок 1475 | SFX F енок ята енок 1476 | SFX F енок ят енок 1477 | SFX F ая ую ая 1478 | SFX F ая ой ая 1479 | SFX F а у а 1480 | SFX F а ой а 1481 | SFX F ёнок ятами ёнок 1482 | SFX F ёнок ятам ёнок 1483 | SFX F ёнок ятах ёнок 1484 | SFX F ёнок ята ёнок 1485 | SFX F ёнок ят ёнок 1486 | SFX F 0 ю ь 1487 | 1488 | SFX E Y 15 1489 | SFX E ый ей ый 1490 | SFX E ый ее ый 1491 | SFX E ь я ь 1492 | SFX E ь ем ь 1493 | SFX E ь е ь 1494 | SFX E ь ю ь 1495 | SFX E ь ём ь 1496 | SFX E я и я 1497 | SFX E я ей я 1498 | SFX E я ею я 1499 | SFX E я е [^и]я 1500 | SFX E я ю я 1501 | SFX E я ёй я 1502 | SFX E я ёю я 1503 | SFX E е й ее 1504 | 1505 | SFX D Y 5 1506 | SFX D ься ся иться 1507 | SFX D ться ется [ая]ться 1508 | SFX D ться ются [ая]ться 1509 | SFX D иться ятся [^жшщч]иться 1510 | SFX D иться атся [жшщч]иться 1511 | 1512 | SFX B Y 25 1513 | SFX B ыться ойтесь ыться 1514 | SFX B ыться ойся ыться 1515 | SFX B ыть ойте ыть 1516 | SFX B ыть ой ыть 1517 | SFX B ь е ить 1518 | SFX B уться итесь уться 1519 | SFX B уться ись уться 1520 | SFX B уть ите уть 1521 | SFX B уть и уть 1522 | SFX B ться тесь иться 1523 | SFX B ться сь иться 1524 | SFX B ться йтесь [аея]ться 1525 | SFX B ться йся [аея]ться 1526 | SFX B ть йте [аея]ть 1527 | SFX B ть й [аея]ть 1528 | SFX B сь тесь ись 1529 | SFX B ся тесь йся 1530 | SFX B ся тесь [^т]ься 1531 | SFX B оться итесь оться 1532 | SFX B оться ись оться 1533 | SFX B оть ите оть 1534 | SFX B оть и оть 1535 | SFX B ить и ить 1536 | SFX B 0 те [ий] 1537 | SFX B 0 те [^ст]ь 1538 | 1539 | SFX A Y 93 1540 | SFX A ый ую ый 1541 | SFX A ый ому [^ц]ый 1542 | SFX A ый ом [^ц]ый 1543 | SFX A ый ой [^ц]ый 1544 | SFX A ый ого [^ц]ый 1545 | SFX A ый ое [^ц]ый 1546 | SFX A ый ою [^ц]ый 1547 | SFX A ый ему цый 1548 | SFX A ый ем цый 1549 | SFX A ый ей цый 1550 | SFX A ый его цый 1551 | SFX A ый ее цый 1552 | SFX A ый ая ый 1553 | SFX A ой ыми [^гхкжшщч]ой 1554 | SFX A ой ым [^гхкжшщч]ой 1555 | SFX A ой ых [^гхкжшщч]ой 1556 | SFX A ой ые [^гхкжшщч]ой 1557 | SFX A ой ую ой 1558 | SFX A ой ому ой 1559 | SFX A ой ом ой 1560 | SFX A ой ого ой 1561 | SFX A ой ое ой 1562 | SFX A ой ими [гхкжшщч]ой 1563 | SFX A ой им [гхкжшщч]ой 1564 | SFX A ой их [гхкжшщч]ой 1565 | SFX A ой ие [гхкжшщч]ой 1566 | SFX A ой ая ой 1567 | SFX A й ми ый 1568 | SFX A й ми [гхк]ий 1569 | SFX A й ми [енржшщч]ий 1570 | SFX A й м ый 1571 | SFX A й м [гхк]ий 1572 | SFX A й м [енржшщч]ий 1573 | SFX A й х ый 1574 | SFX A й х [гхк]ий 1575 | SFX A й х [енржшщч]ий 1576 | SFX A й е ый 1577 | SFX A й е [гхк]ий 1578 | SFX A й е [енржшщч]ий 1579 | SFX A й ю ой 1580 | SFX A ийся уюся [шщ]ийся 1581 | SFX A ийся имся [шщ]ийся 1582 | SFX A ийся имися [шщ]ийся 1583 | SFX A ийся ихся [шщ]ийся 1584 | SFX A ийся иеся [шщ]ийся 1585 | SFX A ийся емуся [шщ]ийся 1586 | SFX A ийся емся [шщ]ийся 1587 | SFX A ийся ейся [шщ]ийся 1588 | SFX A ийся егося [шщ]ийся 1589 | SFX A ийся ееся [шщ]ийся 1590 | SFX A ийся еюся [шщ]ийся 1591 | SFX A ийся аяся [шщ]ийся 1592 | SFX A ий ую [жшщч]ий 1593 | SFX A ий ую [гхк]ий 1594 | SFX A ий яя [ен]ий 1595 | SFX A ий ому [гхк]ий 1596 | SFX A ий ом [гхк]ий 1597 | SFX A ий ой [гхк]ий 1598 | SFX A ий ого [гхк]ий 1599 | SFX A ий ое [гхк]ий 1600 | SFX A ий ою [гхк]ий 1601 | SFX A ий ему [енржшщч]ий 1602 | SFX A ий ем [енржшщч]ий 1603 | SFX A ий ей [енжшщч]ий 1604 | SFX A ий его [енржшщч]ий 1605 | SFX A ий ее [енжшщч]ий 1606 | SFX A ий ею [енжшщч]ий 1607 | SFX A ий ая [жшщч]ий 1608 | SFX A ий ая [гхк]ий 1609 | SFX A ий юю [ен]ий 1610 | SFX A е ми [иы]е 1611 | SFX A е м [иы]е 1612 | SFX A е х [иы]е 1613 | SFX A 0 ыми в 1614 | SFX A 0 ыми ин 1615 | SFX A 0 ым в 1616 | SFX A 0 ым ин 1617 | SFX A 0 ых в 1618 | SFX A 0 ых ин 1619 | SFX A 0 ы в 1620 | SFX A 0 ы ин 1621 | SFX A 0 у в 1622 | SFX A 0 у ин 1623 | SFX A 0 ому ин 1624 | SFX A 0 ом в 1625 | SFX A 0 ом ин 1626 | SFX A 0 ой в 1627 | SFX A 0 ой ин 1628 | SFX A 0 ого ин 1629 | SFX A 0 о в 1630 | SFX A 0 о ин 1631 | SFX A 0 а в 1632 | SFX A 0 а ин 1633 | -------------------------------------------------------------------------------- /help/help.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ####################################### 4 | # Print a help for given script 5 | # Arguments: 6 | # script name 7 | ####################################### 8 | 9 | help=$(cat ${BASH_SOURCE%/*}/$1.md) 10 | help=${help///\\033[1m} 11 | help=${help//<\/b>/\\033[22m} 12 | help=${help//"\`\`\`"/"'"} 13 | help=${help//"\`"/"'"} 14 | help=${help//"==="/""} 15 | help=${help//"=="/""} 16 | echo -e "$help" | less -RFX 17 | -------------------------------------------------------------------------------- /help/nancy.md: -------------------------------------------------------------------------------- 1 | DESCRIPTION 2 | == 3 | The Nancy Command Line Interface is a unified way to manage database 4 | experiments. 5 | 6 | Nancy is a member of Postgres.ai's Artificial DBA team responsible for 7 | conducting experiments. 8 | 9 | SYNOPSYS 10 | == 11 | nancy [parameters] 12 | 13 | AVAILABLE COMMANDS 14 | == 15 | * help 16 | * prepare-database (WIP) 17 | * prepare-workload 18 | * run 19 | -------------------------------------------------------------------------------- /help/nancy_prepare_workload.md: -------------------------------------------------------------------------------- 1 | COMMAND 2 | == 3 | run 4 | 5 | DESCRIPTION 6 | == 7 | Nancy is a member of Postgres.ai's Artificial DBA team responsible for 8 | conducting experiments. 9 | 10 | Use 'nancy prepare-workload' to prepare real-world workload based on Postgres 11 | logs from any of your real Postgres server. 12 | 13 | WIP! Not finished. More details TBD later. 14 | 15 | SEE ALSO 16 | == 17 | 18 | nancy help 19 | 20 | nancy run help 21 | -------------------------------------------------------------------------------- /help/nancy_run.md: -------------------------------------------------------------------------------- 1 | COMMAND 2 | == 3 | run 4 | 5 | DESCRIPTION 6 | === 7 | Use 'nancy run' to perform a single run for a database experiment. 8 | 9 | A DB experiment consists of one or more 'runs'. For example, if Nancy is being 10 | used to verify that a new index will affect performance only in a positive 11 | way, two runs are needed. If one needs to only collect query plans for each 12 | query group, a single run is enough. And finally, if there is a goal to find 13 | an optimal value for some PostgreSQL setting, multiple runs will be needed to 14 | check how various values of the specified setting affect performance of the 15 | specified database and workload. 16 | 17 | An experimental run needs the following 4 items to be provided as an input: 18 | * environment: hardware or cloud instance type, PostgreSQL version, etc; 19 | * database: copy or clone of the database; 20 | * workload: 'real' workload or custom SQL; 21 | * (optional) delta (a.k.a. target): some DB change to be evaluated: 22 | * PostgreSQL config changes, or 23 | * some DDL (or arbitrary SQL) such as 'CREATE INDEX ...', or 24 | * theoretically, anything else. 25 | 26 | OPTIONS 27 | === 28 | NOTICE: A value for a string option that starts with 'file://' is treated as 29 | a path to a local file. A string value starting with 's3://' is 30 | treated as a path to remote file located in S3 (AWS S3 or analog). 31 | Otherwise, a string values is considered as 'content', not a link to 32 | a file. 33 | 34 | --debug (boolean) 35 | 36 | Turn on debug logging. This significantly increases the level of verbosity 37 | of messages being sent to STDOUT. 38 | 39 | --keep-alive (integer) 40 | 41 | How many seconds the entity (Docker container, Docker machine) will remain 42 | alive after the main activity of the run is finished. Useful for 43 | debugging (using ssh access to the container), for serialization of 44 | multiple experimental runs, for optimization of resource (re-)usage. 45 | 46 | WARNING: in clouds, use it with care to avoid unexpected expenses. 47 | 48 | --run-on (string) 49 | 50 | Where the experimental run will be performed. Allowed values: 51 | 52 | * 'localhost' (default) 53 | * 'aws' 54 | * 'gcp' (WIP, not yet implemented) 55 | 56 | If 'localhost' is specified (or --run-on is omitted), Nancy will perform the 57 | run on the localhost in a Docker container so ('docker run' must work 58 | locally). 59 | 60 | If 'aws' is specified, Nancy will use a Docker machine (EC2 Spot Instance) 61 | with a single container on it. 62 | 63 | --tmp-path (string) 64 | 65 | Path to the temporary directory on the current machine (where 'nancy run' is 66 | being invoked), to store various files while preparing them to be shipped to 67 | the experimental container/machine. Default: '/tmp'. 68 | 69 | --container-id (string) 70 | 71 | If specified, new container/machine will not be created. Instead, the existing 72 | one will be reused. This might be a significant optimization for a series of 73 | experimental runs to be executed sequentially. 74 | 75 | WARNING: This option is to be used only with read-only workloads. 76 | 77 | WIP: Currently, this option works only with '--run-on localhost'. 78 | 79 | --pg-version (string) 80 | 81 | Specify the major version of PostgreSQL. Allowed values: 82 | 83 | * '9.6' 84 | * '10' 85 | * '11' 86 | * '12' (default) 87 | 88 | Currently, there is no way to specify the minor version – it is always the 89 | most recent version, available in the official PostgreSQL APT repository (see 90 | https://www.postgresql.org/download/linux/ubuntu/). 91 | 92 | --pg-config (string) 93 | 94 | PostgreSQL config to be used (may be partial). 95 | 96 | --pg-config-auto (enum: oltp|olap) 97 | 98 | Perform "auto-tuning" for PostgreSQL config. Allowed values: 99 | 100 | * 'oltp' to auto-tune Postgres for OLTP workload, 101 | * 'olap' to auto-tune Postgres for OLAP (analytical) workload. 102 | 103 | This option can be combined with "--pg-config" – in this case, it will be 104 | applied *after* it (so "auto-tuning" values will be added to the end of 105 | the postgresql.conf file). 106 | 107 | --db-prepared-snapshot (string) 108 | 109 | Reserved / Not yet implemented. 110 | 111 | --db-dump (string) 112 | 113 | Database dump (created by pg_dump) to be used as an input. May be: 114 | 115 | * path to dump file (must start with 'file://' or 's3://'), may be: 116 | * plain dump made with 'pg_dump', 117 | * gzip-compressed plain dump ('*.gz'), 118 | * bzip2-compressed plain dump ('*.bz2'), 119 | * dump in "custom" format, made with 'pg_dump -Fc ..' ('*.pgdmp'), 120 | * sequence of SQL commands specified as in a form of plain text. 121 | 122 | --db-name (string) 123 | 124 | Name of database which must be tested. Name 'test' is internal used name, 125 | so is not correct value. 126 | 127 | --db-ebs-volume-id (string) 128 | 129 | ID of an AWS EBS volume, containing the database backup (made with pg_basebackup). 130 | 131 | In the volume's root directory, the following two files are expected: 132 | * base.tar.gz 133 | * pg_xlog.tar.gz for Postgres version up to 9.6 or pg_wal.tar.gz for Postgres 10+ 134 | 135 | The following command can be used to get such files: 136 | 137 | pg_basebackup -U postgres -zPFt -Z 5 -D /path/to/ebs/volume/root 138 | 139 | Here '-Z 5' means that level 5 to be used for compression, you can choose any value from 0 to 9. 140 | 141 | --db-pgbench (string) 142 | 143 | Initialize database for pgbench. Contains pgbench init arguments: 144 | 145 | Example: `nancy run --db-pgbench "-s 100"` 146 | 147 | --db-local-pgdata 148 | 149 | Path of Postgres pgdata placed on local storage to use in experiments. All changes at database, 150 | which done during experiment will be stored. 151 | 152 | --pgdata-dir 153 | 154 | The path of Postgres pgdata is placed in local storage to use it in experiments. 155 | All changes to the database, which are done during experiments will be stored. 156 | 157 | --commands-after-container-init (string) 158 | 159 | Shell commands to be executed after the container initialization. Can be used 160 | to add additional software such as Postgres extensions not present in 161 | the main contrib package. 162 | 163 | --sql-before-db-restore (string) 164 | 165 | Additional SQL queries to be executed before the database is initiated. 166 | Applicable only when '--db-dump' is used. 167 | 168 | --sql-after-db-restore (string) 169 | 170 | Additional SQL queries to be executed once the experimental database is 171 | initiated and ready to accept connections. 172 | 173 | --workload-real (string) 174 | 175 | 'Real' workload – path to the file prepared by using 'nancy prepare-workload'. 176 | 177 | --workload-real-replay-speed (integer) 178 | 179 | The speed of replaying of the 'real workload'. Useful for stress-testing 180 | and forecasting the performance of the database under heavier workloads. 181 | 182 | --workload-custom-sql (string) 183 | 184 | SQL queries to be used as workload. These queries will be executed in a signle 185 | database session. 186 | 187 | --workload-pgbench (string) 188 | 189 | pgbench arguments to pass for tests. Ex: "-c 10 -j 4 -t 1000" 190 | 191 | --workload-basis (string) 192 | 193 | Reserved / Not yet implemented. 194 | 195 | --delta-sql-do (string) 196 | 197 | SQL changing database somehow before running workload. For example, DDL: 198 | 199 | create index i_t1_experiment on t1 using btree(col1); 200 | 201 | --delta-sql-undo (string) 202 | 203 | SQL reverting changes produced by those specified in the value of the 204 | '--delta-sql-do' option. Reverting allows to serialize multiple runs, but it 205 | might be not possible in some cases. 'UNDO SQL' example reverting index 206 | creation: 207 | 208 | drop index i_t1_experiment; 209 | 210 | --delta-config (string) 211 | 212 | Config changes to be applied to postgresql.conf before running workload. 213 | Once configuration changes are made, PostgreSQL is restarted. Example: 214 | 215 | random_page_cost = 1.1 216 | 217 | --artifacts-destination (string) 218 | 219 | Path to a local ('file://...') or S3 ('s3://...') directory where artifacts 220 | of the experimental run will be placed. Among these artifacts: 221 | 222 | * detailed performance report in JSON format 223 | * whole PostgreSQL log, gzipped 224 | * full PostgreSQL config used in this experimental run 225 | 226 | --artifacts-dirname 227 | 228 | Folder name where will be saved artifacts files. 229 | 230 | --aws-ec2-type (string) 231 | 232 | Type of EC2 instance to be used. To keep budgets low, EC2 Spot instances will 233 | be utilized and automatic detections of the lowest price in the current AZ 234 | will be performed. 235 | 236 | WARNING: 'i3-metal' instances are not currently supported (WIP). 237 | 238 | The option may be used only with '--run-on aws'. 239 | 240 | --aws-keypair-name (string) 241 | 242 | The name of key pair to be used on EC2 instance to allow ssh access. Must 243 | correspond to SSH key file specified in the '--aws-ssh-key-path' option. 244 | 245 | The option may be used only with '--run-on aws'. 246 | 247 | --aws-ssh-key-path (string) 248 | 249 | Path to SSH key file (usually, has '.pem' extension). 250 | 251 | The option may be used only with '--run-on aws'. 252 | 253 | --aws-ebs-volume-size (string) 254 | 255 | Size (in gigabytes) of EBS volume to be attached to the EC2 instance. 256 | 257 | --aws-region (string) 258 | 259 | Region for creating AWS EC2 instance 260 | 261 | --aws-zone (letter) 262 | 263 | Zone for creating AWS EC2 spot in region given by --aws-zone. 264 | 265 | --aws-zfs 266 | 267 | Attach local NVME drive to 'i3' instance and format it with ZFS. 268 | Tunning options are applied: atime=off, recordsize=8k, logbias=throughput. 269 | ARC MAX is set to 30% of RAM or at least 1GB. 270 | 271 | Otherwise, Ext4 will be used with the following options: 272 | noatime, data=writeback, barrier=0, nobh 273 | 274 | --aws-block-duration (integer) 275 | 276 | EC2 spot max live time in minutes. This value must be a multiple 277 | of 60 (60, 120, 180, 240, 300, or 360). Default value is 0 - no time limit. 278 | 279 | --s3cfg-path 280 | 281 | The path the '.s3cfg' configuration file to be used when accessing files in 282 | S3. This file must be local and must be specified if some options' values are 283 | in 's3://***' format. 284 | 285 | See also: https://github.com/s3tools/s3cmd 286 | 287 | --config 288 | 289 | The path to configuration file with description of deltas for series experiments. 290 | File expected as Yaml file, but without multiline values. File should describe 291 | array of runs like follow: 292 | 293 | run: 294 | 0: 295 | delta_ddl_do: select now(); select now(); 296 | delta_ddl_undo: select now(); 297 | # delta_config: max_wal_size = 2048MB 298 | 1: 299 | # delta_ddl_do: select now(); 300 | # delta_ddl_undo: select now(); 301 | delta_config: max_wal_size = 4092MB 302 | # 2: 303 | # delta_ddl_do: select now(); 304 | # delta_ddl_undo: select now(); 305 | # delta_config: max_wal_size = 4092MB 306 | 307 | For every experinment can be set three fields: delta_ddl_do, delta_ddl_undo and 308 | delta_config. If param delta_ddl_do is used then param delta_ddl_undo must be 309 | given also and vise versa. If you need enumerate several configuration params 310 | as delta_config value you should divide them by ';' 311 | 312 | --no-pgbadger 313 | 314 | Turn off use pgbadger to prepare reports. 315 | 316 | --no-perf 317 | 318 | Turn off use perf and FlameGraphs. 319 | 320 | --less-output 321 | 322 | Turn off all output besides errors and results statistic. 323 | 324 | SEE ALSO 325 | == 326 | nancy help 327 | -------------------------------------------------------------------------------- /nancy: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # 2018–2019 © Postgres.ai 4 | # 5 | # A wrapper for all Nancy CLI commands. 6 | # Usage: use 'nancy help' for help. 7 | # 8 | 9 | DEBUG=0 10 | cmd="" 11 | 12 | case "$1" in 13 | help ) 14 | source ${BASH_SOURCE%/*}/help/help.sh "nancy" 15 | exit 1; 16 | ;; 17 | * ) 18 | word="${1/-/_}" 19 | if [[ ! -f "${BASH_SOURCE%/*}/nancy_$word.sh" ]]; then 20 | >&2 echo "ERROR: Unknown command: $word." 21 | >&2 echo "Try 'nancy help'" 22 | exit 1 23 | fi 24 | cmd="${BASH_SOURCE%/*}/nancy_$word.sh" 25 | shift; 26 | ;; 27 | esac 28 | 29 | while [ -n "$1" ]; do 30 | if [ "$1" == "--debug" ]; then 31 | DEBUG=1 32 | fi 33 | if [ ${1%"${1#??}"} = '--' ]; then 34 | cmd="$cmd $1" 35 | else 36 | cmd="$cmd \"$1\"" 37 | fi 38 | shift 39 | done 40 | 41 | [[ "$DEBUG" -eq "1" ]] && echo "CMD: $cmd" 42 | 43 | eval "$cmd" 44 | -------------------------------------------------------------------------------- /nancy_describe.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # 2018–2019 © Postgres.ai 4 | # 5 | # Describe one or more experimental runs, taking 6 | # collection(s) of artifacts as input. 7 | 8 | DEBUG=false 9 | VERBOSE_OUTPUT_REDIRECT='' 10 | ARTIFACTS_PATH='' 11 | 12 | ####################################### 13 | # Print a help 14 | # Globals: 15 | # None 16 | # Arguments: 17 | # None 18 | # Returns: 19 | # None 20 | ####################################### 21 | function help() { 22 | echo -e "Describe results of nancy run tests. To start use: 23 | nancy describe %artifacts_directory_path% 24 | " | less -RFX 25 | } 26 | 27 | ####################################### 28 | # Print an error/warning/notice message to STDERR 29 | # Globals: 30 | # None 31 | # Arguments: 32 | # (text) Error message 33 | # Returns: 34 | # None 35 | ####################################### 36 | function err() { 37 | echo "[$(date +'%Y-%m-%dT%H:%M:%S%z')] $@" >&2 38 | } 39 | 40 | ####################################### 41 | # Print a debug-level message to STDOUT 42 | # Globals: 43 | # DEBUG 44 | # Arguments: 45 | # (text) Message 46 | # Returns: 47 | # None 48 | ####################################### 49 | function dbg() { 50 | if $DEBUG ; then 51 | msg "DEBUG: $@" 52 | fi 53 | } 54 | 55 | ####################################### 56 | # Print an message to STDOUT 57 | # Globals: 58 | # None 59 | # Arguments: 60 | # (text) Message 61 | # Returns: 62 | # None 63 | ####################################### 64 | function msg() { 65 | echo "[$(date +'%Y-%m-%dT%H:%M:%S%z')] $@" 66 | } 67 | 68 | ####################################### 69 | # Print an 5 top slowest queries 70 | # Globals: 71 | # ARTIFACTS_PATH 72 | # Arguments: 73 | # (int) count of slowest queries 74 | # Returns: 75 | # None 76 | ####################################### 77 | function out_top_slowest() { 78 | local top_count=$1 79 | local i=0 80 | local j=1 81 | while : ; do 82 | let j=$i+1 83 | echo -e " Slowest query #$j." 84 | duration=$(cat $FILE_PATH | jq '.top_slowest | .['$i'] | .[0]') 85 | duration="${duration/\"/}" 86 | duration="${duration/\"/}" 87 | query=$(cat $FILE_PATH | jq '.top_slowest | .['$i'] | .[2]') 88 | query="${query//'\\n'/}" 89 | query="${query//'\\\"'/'"'}" #' 90 | echo -e " Duration is: $duration ms" 91 | echo -e " Query text: $query\n" 92 | let i=$i+1 93 | [[ "$i" -eq "$top_count" ]] && break; 94 | done 95 | } 96 | 97 | ####################################### 98 | # Print an durations of slowest queries in different runs 99 | # Globals: 100 | # ARTIFACTS_PATH 101 | # Arguments: 102 | # (int) count of slowest queries to analyze 103 | # Returns: 104 | # (int) 1 if is not series experiment 105 | ####################################### 106 | function compare_series_slowest() { 107 | local top_count=$1 108 | # Check is series experiment 109 | if [[ ! -f "$ARTIFACTS_PATH/pgbadger.1.json" ]]; then 110 | msg "Experiment is not series." 111 | return 1 112 | fi 113 | local file_path=$ARTIFACTS_PATH/pgbadger.1.json 114 | local i=0 115 | local j=1 116 | while : ; do 117 | let j=$i+1 118 | echo -e " Slowest query #$j." 119 | duration=$(cat $file_path | jq '.top_slowest | .['$i'] | .[0]') 120 | duration="${duration/\"/}" 121 | duration="${duration/\"/}" 122 | query=$(cat $file_path | jq '.top_slowest | .['$i'] | .[2]') 123 | query_text="${query//'\\n'/}" 124 | query_text="${query_text//'\\\"'/'"'}" #' 125 | echo -e " Slowest query text: $query_text" 126 | echo -e " Run 1 duration is:\t$duration ms" 127 | local fi=2 128 | while : ; do 129 | if [[ ! -f "$ARTIFACTS_PATH/pgbadger.$fi.json" ]]; then 130 | dbg "File $ARTIFACTS_PATH/pgbadger.$fi.json not found" 131 | break 132 | fi 133 | local qi=0 134 | local fcount=$(cat $ARTIFACTS_PATH/pgbadger.$fi.json | jq '.top_slowest | length') 135 | while : ; do 136 | qduration=$(cat $ARTIFACTS_PATH/pgbadger.$fi.json | jq '.top_slowest | .['$qi'] | .[0]') 137 | qduration="${qduration/\"/}" 138 | qduration="${qduration/\"/}" 139 | qquery=$(cat $ARTIFACTS_PATH/pgbadger.$fi.json | jq '.top_slowest | .['$qi'] | .[2]') 140 | if [[ "$query" == "$qquery" ]]; then 141 | echo -e " Run $fi duration is:\t$qduration ms" 142 | fi 143 | let qi=$qi+1 144 | [[ "$qi" -eq "$fcount" ]] && break; 145 | done 146 | let fi=$fi+1 147 | done 148 | let i=$i+1 149 | [[ "$i" -eq "$top_count" ]] && break; 150 | done 151 | } 152 | 153 | while [ $# -gt 0 ]; do 154 | case "$1" in 155 | help ) 156 | help 157 | exit ;; 158 | -d | --debug ) 159 | DEBUG=true 160 | VERBOSE_OUTPUT_REDIRECT='' 161 | shift ;; 162 | * ) 163 | option=$1 164 | option="${option##*( )}" 165 | option="${option%%*( )}" 166 | if [[ ! -d $option ]]; then 167 | err "Artifacts directory not given" 168 | exit 1 169 | else 170 | ARTIFACTS_PATH=$option 171 | fi 172 | break ;; 173 | esac 174 | done 175 | 176 | if [[ -z "$ARTIFACTS_PATH" ]]; then 177 | err "Artifacts directory not given" 178 | exit 1 179 | fi 180 | 181 | #if [[ -f "$ARTIFACTS_PATH/pgreplay.txt" ]]; then 182 | # cat "$ARTIFACTS_PATH/pgreplay.txt" 183 | #fi 184 | 185 | if [[ -f "$ARTIFACTS_PATH/pgbadger.json" ]]; then 186 | FILE_PATH=$ARTIFACTS_PATH/pgbadger.json 187 | echo -e "------------------------------------------------------------------------------" 188 | echo -e "Artifacts (collected in \"$ARTIFACTS_PATH\"):" 189 | echo -e " Postgres config: postgresql.conf" 190 | echo -e " Postgres logs: postgresql.prepare.log.gz (preparation)," 191 | echo -e " postgresql.workload.log.gz (workload)" 192 | echo -e " pgBadger reports: pgbadger.html (for humans)," 193 | echo -e " pgbadger.json (for robots)" 194 | echo -e " Stat stapshots: pg_stat_statements.csv," 195 | echo -e " pg_stat_***.csv" 196 | echo -e " pgreplay report: pgreplay.txt" 197 | echo -e "------------------------------------------------------------------------------" 198 | echo -e "Workload:" 199 | echo -e " Total query time: "$(cat $FILE_PATH | jq '.overall_stat.queries_duration') " ms" 200 | echo -e " Queries: "$(cat $FILE_PATH | jq '.overall_stat.queries_number') 201 | echo -e " Query groups: "$(cat $FILE_PATH | jq '.normalyzed_info | length') 202 | echo -e " Errors: "$(cat $FILE_PATH | jq '.overall_stat.errors_number') 203 | echo -e " Errors groups: "$(cat $FILE_PATH | jq '.error_info | length') 204 | echo -e "------------------------------------------------------------------------------" 205 | elif [[ -f "$ARTIFACTS_PATH/pgbadger.1.json" ]]; then 206 | FILE_PATH=$ARTIFACTS_PATH/pgbadger.1.json 207 | SERIES_COUNT=2 208 | while : ; do 209 | if [[ ! -f "$ARTIFACTS_PATH/pgbadger.$SERIES_COUNT.json" ]]; then 210 | let SERIES_COUNT=$SERIES_COUNT-1 211 | break 212 | fi 213 | let SERIES_COUNT=$SERIES_COUNT+1 214 | done 215 | echo -e "------------------------------------------------------------------------------" 216 | echo -e "Runs count: $SERIES_COUNT" 217 | echo -e "Experiment artifacts collected in \"$ARTIFACTS_PATH/\"." 218 | echo -e "Postgres prepare log: postgresql.prepare.log.gz (preparation)," 219 | echo -e "------------------------------------------------------------------------------" 220 | local i=1; 221 | while : ; do 222 | FILE_PATH="$ARTIFACTS_PATH/pgbadger.$i.json" 223 | echo -e "\n" 224 | echo -e "Run $i" 225 | echo -e "------------------------------------------------------------------------------" 226 | echo -e "Run artifacts (collected in \"$ARTIFACTS_PATH\"):" 227 | echo -e " Postgres config: postgresql.$i.conf" 228 | echo -e " Postgres log: postgresql.workload.$i.log.gz (workload)" 229 | echo -e " pgBadger reports: pgbadger.$i.html (for humans)," 230 | echo -e " pgbadger.$i.json (for robots)" 231 | echo -e " Stat stapshots: pg_stat_statements.$i.csv," 232 | echo -e " pg_stat_***.$i.csv" 233 | echo -e " pgreplay report: pgreplay.$i.txt" 234 | echo -e "------------------------------------------------------------------------------" 235 | echo -e "Workload:" 236 | echo -e " Total query time: "$(cat $FILE_PATH | jq '.overall_stat.queries_duration') " ms" 237 | echo -e " Queries: "$(cat $FILE_PATH | jq '.overall_stat.queries_number') 238 | echo -e " Query groups: "$(cat $FILE_PATH | jq '.normalyzed_info | length') 239 | echo -e " Errors: "$(cat $FILE_PATH | jq '.overall_stat.errors_number') 240 | echo -e " Errors groups: "$(cat $FILE_PATH | jq '.error_info | length') 241 | echo -e "------------------------------------------------------------------------------" 242 | let i=$i+1 243 | [[ "$i" -eq "$SERIES_COUNT" ]] && break; 244 | done 245 | fi 246 | compare_series_slowest 5 247 | if [ $? -ne 0 ]; then 248 | out_top_slowest 5 249 | fi 250 | -------------------------------------------------------------------------------- /nancy_prepare_workload.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # 2018–2019 © Postgres.ai 4 | # 5 | # Prepare worklod file based on a full production Postgres log. 6 | # 7 | 8 | DEBUG=0 9 | 10 | ## Get command line params 11 | while true; do 12 | case "$1" in 13 | help ) 14 | source ${BASH_SOURCE%/*}/help/help.sh "nancy_prepare_workload" 15 | exit ;; 16 | -d | --debug ) DEBUG=1; shift ;; 17 | --db-name ) 18 | DB_NAME="$2"; shift 2 ;; 19 | --output ) 20 | OUTPUT="$2"; shift 2 ;; 21 | -- ) 22 | >&2 echo "ERROR: Invalid option '$1'" 23 | exit 1 24 | break ;; 25 | * ) 26 | if [ "${1:0:2}" == "--" ]; then 27 | >&2 echo "ERROR: Invalid option '$1'. Please double-check options." 28 | exit 1 29 | else 30 | INPUT="$1" 31 | fi 32 | break ;; 33 | esac 34 | done 35 | 36 | if [ $DEBUG -eq 1 ]; then 37 | echo "debug: ${DEBUG}" 38 | echo "input: ${INPUT}" 39 | echo "output: ${OUTPUT}" 40 | echo "db_name: ${DB_NAME}" 41 | fi 42 | 43 | if [ -z ${INPUT+x} ]; then 44 | >&2 echo "ERROR: the input (path to Postgres log file) is not specified." 45 | exit 1; 46 | fi 47 | 48 | if [ -z ${OUTPUT+x} ]; then 49 | >&2 echo "ERROR: the output path is not specified." 50 | exit 1; 51 | fi 52 | 53 | awk_version=$((awk -Wversion 2>/dev/null || awk --version) | head -n1) 54 | if [ "${awk_version:0:3}" != "GNU" ]; then 55 | >&2 echo "ERROR: GNU awk is required. Your awk version is: ${awk_version}. Try to install gawk." 56 | exit 1; 57 | fi 58 | 59 | pgreplay_version=$(pgreplay -v 2>/dev/null) 60 | if [ "${pgreplay_version:0:8}" != "pgreplay" ]; then 61 | >&2 echo "ERROR: pgreplay is not installed." 62 | exit 1; 63 | fi 64 | 65 | bc_version=$(bc -v 2>/dev/null) 66 | if [ "${bc_version:0:2}" != "bc" ]; then 67 | >&2 echo "ERROR: bc is not installed." 68 | exit 1; 69 | fi 70 | 71 | cat $INPUT \ 72 | | sed -r 's/^([0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{3} .*)$/\nNANCY_NEW_LINE_SEPARATOR\n\1/' \ 73 | | sed "s/\"\"/NANCY_TWO_DOUBLE_QUOTES_SEPARATOR/g" \ 74 | | awk -v dbname="\"$DB_NAME\"" ' 75 | BEGIN { 76 | RS="\nNANCY_NEW_LINE_SEPARATOR\n"; 77 | FPAT = "([^,]+)|(\"[^\"]+\")" 78 | OFS="," 79 | } 80 | { 81 | if ($3 == dbname && substr($14, 0, 11) == "\"duration: ") { 82 | duration_ms = substr($14, 0, 30) 83 | if (match($14, /^"duration: ([^ ]+) ms statement: (.*)$/, match_arr)) { 84 | duration = match_arr[1] * 1000 85 | statement = "\"statement: " match_arr[2] 86 | } 87 | "date -u -d @$(echo \"scale=6; ($(date -u --date=\"" $1 "\" +'%s%6N') - " duration \ 88 | ") / 1000000\" | bc) +\"%Y-%m-%d %H:%M:%S.%6N%:::z\" | tr -d \"\\n\"" | getline res_ts 89 | print res_ts,"\"postgres\"","\"test\"",$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,statement ",,,,,,,," 90 | } 91 | }' \ 92 | | sed "s/NANCY_TWO_DOUBLE_QUOTES_SEPARATOR/\"\"/g" \ 93 | | pgreplay -f -c -o "$OUTPUT" 94 | -------------------------------------------------------------------------------- /pg_badger_parsing.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # written by Yorick 3 | # 4 | # Usage: pg_badger_parsing.sh - for parsing /var/log/postgresql/ after logrotate 5 | # pg_badger_parsing.sh postgresql.log - specifying the file 6 | # 7 | # Requires: apt-get install libjson-xs-perl 8 | # 9 | 10 | hostname=$(hostname -f) 11 | logfile=$NANCY_LOGFILE 12 | 13 | [ "$logfile" = '' ] && logfile=$1 14 | 15 | if [ ! -s ~/.s3cfg ] 16 | then 17 | project=$NANCY_PROJECT 18 | [ "$(psql -X -A -t postgres_ai -c "select s3_access_key,s3_secret_key,s3_region from project where name='$project';" 2>/dev/null | wc -l)" -ne 1 ] && echo "FAIL: project=$project is invalid, exit" && exit 1 19 | s3cfg=$(psql -X -A -t postgres_ai -c "select s3_access_key,s3_secret_key,s3_region from project where name='$project';") 20 | (echo '[default]' 21 | echo "access_key = $(echo "$s3cfg" | awk -F '|' '{print $1}')" 22 | echo "secret_key = $(echo "$s3cfg" | awk -F '|' '{print $2}')" 23 | echo "region = $(echo "$s3cfg" | awk -F '|' '{print $3}')" 24 | ) > ~/.s3cfg 25 | fi 26 | 27 | if [ "$logfile" != '' ] 28 | then 29 | [ ! -s $logfile ] && echo "FAIL: file=$file is empty or absent, exit" && exit 1 30 | pgbadger -j 4 --prefix '%t [%p]: [%l-1] db=%d,user=%u (%a,%h)' "$logfile" -f stderr -o "$logfile.json" && gzip -vf "$logfile.json" && s3cmd put "$logfile.json.gz" s3://p-dumps/${hostname}-manual/ 31 | echo "Listing (on S3 storage):" 32 | s3cmd ls s3://p-dumps/${hostname}-manual/ 33 | else 34 | version=postgresql-9.6-main 35 | date=$(date -d 'now' '+%Y%m%d') 36 | logdir=/var/log/postgresql 37 | pgbadger -j 4 --prefix '%t [%p]: [%l-1] db=%d,user=%u (%a,%h)' ${logdir}/${version}.log-${date}.gz -f stderr -o ${logdir}/${version}.json-${date} && gzip -vf ${logdir}/${version}.json-${date} && s3cmd put ${logdir}/${version}.*-${date}.gz s3://p-dumps/${hostname}/ 38 | echo "Listing (on S3 storage):" 39 | s3cmd ls s3://p-dumps/$hostname/ 40 | fi 41 | -------------------------------------------------------------------------------- /tests/nancy_cli_run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | export PATH=$PATH:${BASH_SOURCE%/*}/.. 4 | 5 | output=$(nancy run --run-on aws 2>&1) 6 | 7 | if [[ $output =~ "ERROR: AWS keypair name and SSH key file must be specified to run on AWS EC2." ]]; then 8 | echo -e "\e[36mOK\e[39m" 9 | else 10 | >&2 echo -e "\e[31mFAILED\e[39m" 11 | >&2 echo -e "Output: $output" 12 | exit 1 13 | fi 14 | -------------------------------------------------------------------------------- /tests/nancy_cli_run_no_optons.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | output=$(${BASH_SOURCE%/*}/../nancy run --run-on aws 2>&1) 4 | 5 | if [[ $output =~ "ERROR: AWS keypair name and SSH key file must be specified to run on AWS EC2." ]]; then 6 | echo -e "\e[36mOK\e[39m" 7 | else 8 | >&2 echo -e "\e[31mFAILED\e[39m" 9 | >&2 echo -e "Output: $output" 10 | exit 1 11 | fi 12 | -------------------------------------------------------------------------------- /tests/nancy_cli_unknown.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | output=$(${BASH_SOURCE%/*}/../nancy init --run-on aws 2>&1) 4 | 5 | if [[ $output =~ "ERROR: Unknown command" ]]; then 6 | echo -e "\e[36mOK\e[39m" 7 | else 8 | >&2 echo -e "\e[31mFAILED\e[39m" 9 | >&2 echo -e "Output: $output" 10 | exit 1 11 | fi 12 | -------------------------------------------------------------------------------- /tests/nancy_prepare_workload.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | output=$( \ 4 | ${BASH_SOURCE%/*}/../nancy prepare-workload --db-name testci \ 5 | --output ./test.replay ./.circleci/sample.log \ 6 | 2>&1 7 | ) 8 | if [[ $output =~ "Total SQL statements processed: 2" ]]; then 9 | echo -e "\e[36mOK\e[39m" 10 | else 11 | >&2 echo -e "\e[31mFAILED\e[39m" 12 | >&2 echo -e "Output: $output" 13 | exit 1 14 | fi 15 | 16 | -------------------------------------------------------------------------------- /tests/nancy_run_abnormal.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | realpath() { 4 | [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}" 5 | } 6 | 7 | src_dir=$(dirname $(dirname $(realpath "$0")))"/.circleci" 8 | 9 | output=$( 10 | ${BASH_SOURCE%/*}/../nancy run \ 11 | --commands-after-container-init "exit 1" \ 12 | --db-pgbench "-s 1" \ 13 | --workload-pgbench "-t 1" 2>&1 14 | ) 15 | 16 | if [[ $output =~ "Check artifacts to understand the reasons." ]]; then 17 | echo -e "\e[36mOK\e[39m" 18 | else 19 | >&2 echo -e "\e[31mFAILED\e[39m" 20 | >&2 echo -e "Output: $output" 21 | exit 1 22 | fi 23 | -------------------------------------------------------------------------------- /tests/nancy_run_aws_no_keys.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | output=$(${BASH_SOURCE%/*}/../nancy_run.sh --run-on aws 2>&1) 4 | 5 | if [[ $output =~ "ERROR: AWS keypair name and SSH key file must be specified to run on AWS EC2." ]]; then 6 | echo -e "\e[36mOK\e[39m" 7 | else 8 | >&2 echo -e "\e[31mFAILED\e[39m" 9 | >&2 echo -e "Output: $output" 10 | exit 1 11 | fi 12 | -------------------------------------------------------------------------------- /tests/nancy_run_aws_pgdata_dir.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | realpath() { 4 | [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}" 5 | } 6 | 7 | src_dir=$(dirname $(dirname $(realpath "$0")))"/.circleci" 8 | if [ ! -d "$src_dir/tmp" ]; then 9 | mkdir "$src_dir/tmp" 10 | fi 11 | 12 | output=$( 13 | ${BASH_SOURCE%/*}/../nancy run \ 14 | --run-on aws \ 15 | --workload-custom-sql "file://$src_dir/custom.sql" \ 16 | --db-dump "file://$src_dir/test.dump.sql" \ 17 | --db-local-pgdata ./ \ 18 | --pgdata-dir ./ \ 19 | --tmp-path $src_dir/tmp 2>&1 20 | ) 21 | 22 | regex="ERROR: --db-local-pgdata may be specified only for local runs" 23 | if [[ $output =~ $regex ]]; then 24 | echo -e "\e[36mOK\e[39m" 25 | else 26 | >&2 echo -e "\e[31mFAILED\e[39m" 27 | >&2 echo -e "Output: $output" 28 | exit 1 29 | fi 30 | -------------------------------------------------------------------------------- /tests/nancy_run_aws_zfs_i3.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Test ZFS on i3 4 | 5 | # TODO(vyagofarov): fix after migration to GitLab CI/CD 6 | 7 | #output=$( 8 | # bash -x ${BASH_SOURCE%/*}/../nancy run \ 9 | # --run-on aws \ 10 | # --aws-keypair-name awskey \ 11 | # --aws-ssh-key-path /path/.ssh/awskey.pem \ 12 | # --aws-ec2-type i3.large \ 13 | # --db-dump "create table hello_world as select i from generate_series(1, (10)::int) _(i);" \ 14 | # --workload-custom-sql "select 1" \ 15 | # --no-pgbadger \ 16 | # --aws-zfs \ 17 | # 2>&1 18 | #) 19 | # 20 | #exit_code="$?" 21 | # 22 | #if [[ "$exit_code" -ne "0" ]]; then 23 | # echo -e "\e[31mFAILED\e[39m" >&2 24 | # echo -e "Output: $output" >&2 25 | # exit 1 26 | #else 27 | # echo -e "\e[36mOK\e[39m" 28 | #fi 29 | # 30 | -------------------------------------------------------------------------------- /tests/nancy_run_before_init_code.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | realpath() { 4 | [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}" 5 | } 6 | 7 | src_dir=$(dirname $(dirname $(realpath "$0")))"/.circleci" 8 | 9 | output=$( 10 | ${BASH_SOURCE%/*}/../nancy run \ 11 | --sql-before-db-restore "select abs from beforeinittable;" \ 12 | --workload-custom-sql "file://$src_dir/custom.sql" \ 13 | --db-dump "file://$src_dir/test.dump.bz2" \ 14 | --tmp-path $src_dir/tmp \ 15 | 2>&1 16 | ) 17 | 18 | if [[ $output =~ "ERROR: relation \"beforeinittable\" does not exist" ]]; then 19 | echo -e "\e[36mOK\e[39m" 20 | else 21 | >&2 echo -e "\e[31mFAILED\e[39m" 22 | >&2 echo -e "Output: $output" 23 | exit 1 24 | fi 25 | -------------------------------------------------------------------------------- /tests/nancy_run_ebs_disk_size.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # TODO(NikolayS) -aws-ebs-volume-size requires "--run-on aws" – allow these tests in CI 4 | 5 | #output=$( 6 | # ${BASH_SOURCE%/*}/../nancy run \ 7 | # --debug \ 8 | # --run-on aws \ 9 | # --aws-ebs-volume-size 37 \ 10 | # 2>&1 11 | #) 12 | # 13 | #if [[ $output =~ "ebs-volume-size: 37" ]]; then 14 | # echo -e "\e[36mOK\e[39m" 15 | #else 16 | # >&2 echo -e "\e[31mFAILED\e[39m" 17 | # >&2 echo -e "Output: $output" 18 | # exit 1 19 | #fi 20 | -------------------------------------------------------------------------------- /tests/nancy_run_ebs_disk_size_incorrect.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | realpath() { 4 | [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}" 5 | } 6 | 7 | src_dir=$(dirname $(dirname $(realpath "$0")))"/.circleci" 8 | 9 | # TODO(NikolayS) -aws-ebs-volume-size requires "--run-on aws" – allow these tests in CI 10 | 11 | #output=$( 12 | # ${BASH_SOURCE%/*}/../nancy run \ 13 | # --run-on aws \ 14 | # --aws-ebs-volume-size sa \ 15 | # --workload-custom-sql "file://$src_dir/custom.sql" \ 16 | # --db-dump "file://$src_dir/test.dump.bz2" \ 17 | # --tmp-path $src_dir/tmp \ 18 | # 2>&1 19 | #) 20 | # 21 | #if [[ $output =~ "ERROR: ebs-volume-size must be integer." ]]; then 22 | # echo -e "\e[36mOK\e[39m" 23 | #else 24 | # >&2 echo -e "\e[31mFAILED\e[39m" 25 | # >&2 echo -e "Output: $output" 26 | # exit 1 27 | #fi 28 | -------------------------------------------------------------------------------- /tests/nancy_run_invalid_aws_option.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | output=$( 4 | ${BASH_SOURCE%/*}/../nancy run \ 5 | --run-on localhost \ 6 | --aws-keypair-name awskey \ 7 | --aws-ssh-key-path /path/.ssh/awskey.pem \ 8 | --aws-ec2-type i3.large \ 9 | 2>&1 10 | ) 11 | 12 | if [[ $output =~ "may be used only with '--run-on aws'" ]]; then 13 | echo -e "\e[36mOK\e[39m" 14 | else 15 | >&2 echo -e "\e[31mFAILED\e[39m" 16 | >&2 echo -e "Output: $output" 17 | exit 1 18 | fi 19 | -------------------------------------------------------------------------------- /tests/nancy_run_invalid_option.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | output=$(${BASH_SOURCE%/*}/../nancy run --run-on-type test 2>&1) 4 | 5 | if [[ $output =~ "ERROR: Invalid option '--run-on-type'. Please double-check options." ]]; then 6 | echo -e "\e[36mOK\e[39m" 7 | else 8 | >&2 echo -e "\e[31mFAILED\e[39m" 9 | >&2 echo -e "Output: $output" 10 | exit 1 11 | fi 12 | -------------------------------------------------------------------------------- /tests/nancy_run_invalid_spot_duration.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | output=$( 4 | ${BASH_SOURCE%/*}/../nancy run \ 5 | --run-on aws \ 6 | --aws-keypair-name awskey \ 7 | --aws-ssh-key-path /path/.ssh/awskey.pem \ 8 | --aws-ec2-type i3.large \ 9 | --aws-block-duration 30 \ 10 | 2>&1 11 | ) 12 | 13 | if [[ $output =~ "ERROR: The value of '--aws-block-duration' is invalid" ]]; then 14 | echo -e "\e[36mOK\e[39m" 15 | else 16 | >&2 echo -e "\e[31mFAILED\e[39m" 17 | >&2 echo -e "Output: $output" 18 | exit 1 19 | fi 20 | -------------------------------------------------------------------------------- /tests/nancy_run_localhost_connection_str.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | realpath() { 4 | [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}" 5 | } 6 | 7 | src_dir=$(dirname $(dirname $(realpath "$0")))"/.circleci" 8 | 9 | output=$( 10 | ${BASH_SOURCE%/*}/../nancy run \ 11 | --db-dump "create table hello_world as select i, i as id from generate_series(1, 1000) _(i);" \ 12 | --workload-real "file://$src_dir/sample.replay" \ 13 | --tmp-path $src_dir/tmp 2>&1 14 | ) 15 | 16 | if [[ $output =~ " How to connect to" ]]; then 17 | echo -e "\e[36mOK\e[39m" 18 | else 19 | >&2 echo -e "\e[31mFAILED\e[39m" 20 | >&2 echo -e "Output: $output" 21 | exit 1 22 | fi 23 | -------------------------------------------------------------------------------- /tests/nancy_run_localhost_less_output.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | realpath() { 4 | [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}" 5 | } 6 | 7 | src_dir=$(dirname $(dirname $(realpath "$0")))"/.circleci" 8 | 9 | output=$( 10 | ${BASH_SOURCE%/*}/../nancy run \ 11 | --less-output \ 12 | --db-pgbench "-s 1" \ 13 | --workload-pgbench "-t 1" 2>&1 14 | ) 15 | 16 | if ! [[ $output =~ "LOG: Ok, generating html report..." ]]; then 17 | echo -e "\e[36mOK\e[39m" 18 | else 19 | >&2 echo -e "\e[31mFAILED\e[39m" 20 | >&2 echo -e "Output: $output" 21 | exit 1 22 | fi 23 | -------------------------------------------------------------------------------- /tests/nancy_run_localhost_norm_output.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | realpath() { 4 | [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}" 5 | } 6 | 7 | src_dir=$(dirname $(dirname $(realpath "$0")))"/.circleci" 8 | 9 | output=$( 10 | ${BASH_SOURCE%/*}/../nancy run \ 11 | --db-pgbench "-s 1" \ 12 | --workload-pgbench "-t 1" 2>&1 13 | ) 14 | 15 | if [[ $output =~ "LOG: Ok, generating html report..." ]]; then 16 | echo -e "\e[36mOK\e[39m" 17 | else 18 | >&2 echo -e "\e[31mFAILED\e[39m" 19 | >&2 echo -e "Output: $output" 20 | exit 1 21 | fi 22 | -------------------------------------------------------------------------------- /tests/nancy_run_localhost_pgbench.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | realpath() { 4 | [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}" 5 | } 6 | 7 | src_dir=$(dirname $(dirname $(realpath "$0")))"/.circleci" 8 | 9 | output=$( 10 | ${BASH_SOURCE%/*}/../nancy run \ 11 | --db-pgbench "-s 1" \ 12 | --workload-pgbench "-t 1" 2>&1 13 | ) 14 | 15 | regex="Errors:[[:blank:]]*0" 16 | if [[ $output =~ $regex ]]; then 17 | echo -e "\e[36mOK\e[39m" 18 | else 19 | >&2 echo -e "\e[31mFAILED\e[39m" 20 | >&2 echo -e "Output: $output" 21 | exit 1 22 | fi 23 | -------------------------------------------------------------------------------- /tests/nancy_run_localhost_pgdata_dir.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | realpath() { 4 | [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}" 5 | } 6 | 7 | src_dir=$(dirname $(dirname $(realpath "$0")))"/.circleci" 8 | if [ ! -d "$src_dir/tmp" ]; then 9 | mkdir "$src_dir/tmp" 10 | fi 11 | 12 | output=$( 13 | ${BASH_SOURCE%/*}/../nancy run \ 14 | --workload-custom-sql "file://$src_dir/custom.sql" \ 15 | --db-dump "file://$src_dir/test.dump.sql" \ 16 | --db-local-pgdata ./ \ 17 | --pgdata-dir ./ \ 18 | --tmp-path $src_dir/tmp 2>&1 19 | ) 20 | 21 | regex="ERROR: Both --pgdata-dir and --db-local-pgdata are provided" 22 | if [[ $output =~ $regex ]]; then 23 | echo -e "\e[36mOK\e[39m" 24 | else 25 | >&2 echo -e "\e[31mFAILED\e[39m" 26 | >&2 echo -e "Output: $output" 27 | exit 1 28 | fi 29 | -------------------------------------------------------------------------------- /tests/nancy_run_localhost_real_workload.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | realpath() { 4 | [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}" 5 | } 6 | 7 | src_dir=$(dirname $(dirname $(realpath "$0")))"/.circleci" 8 | 9 | output=$( 10 | ${BASH_SOURCE%/*}/../nancy run \ 11 | --db-dump "create table hello_world as select i, i as id from generate_series(1, 1000) _(i); drop role testuser;" \ 12 | --workload-real "file://$src_dir/sample.replay" \ 13 | --tmp-path $src_dir/tmp 2>&1 14 | ) 15 | 16 | regex="Queries:[[:blank:]]*[1-9]" 17 | if [[ $output =~ $regex ]]; then 18 | echo -e "\e[36mOK\e[39m" 19 | else 20 | >&2 echo -e "\e[31mFAILED\e[39m" 21 | >&2 echo -e "Output: $output" 22 | exit 1 23 | fi 24 | -------------------------------------------------------------------------------- /tests/nancy_run_localhost_series.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | realpath() { 4 | [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}" 5 | } 6 | 7 | src_dir=$(dirname $(dirname $(realpath "$0")))"/.circleci" 8 | 9 | output=$( 10 | ${BASH_SOURCE%/*}/../nancy run \ 11 | --less-output \ 12 | --db-pgbench "-s 1" \ 13 | --workload-pgbench "-t 1" \ 14 | --config file://${BASH_SOURCE%/*}/../.circleci/run.yml 2>&1 15 | ) 16 | 17 | if [[ $output =~ "Run #1 done." ]] && [[ $output =~ "Run #2 done." ]] && [[ $output =~ "Run #3 done." ]]; then 18 | echo -e "\e[36mOK\e[39m" 19 | else 20 | >&2 echo -e "\e[31mFAILED\e[39m" 21 | >&2 echo -e "Output: $output" 22 | exit 1 23 | fi 24 | -------------------------------------------------------------------------------- /tests/nancy_run_localhost_simple_dump.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | test_passed=true 3 | 4 | realpath() { 5 | [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}" 6 | } 7 | 8 | src_dir=$(dirname $(dirname $(realpath "$0")))"/.circleci" 9 | 10 | output=$( 11 | ${BASH_SOURCE%/*}/../nancy run \ 12 | --workload-custom-sql "file://$src_dir/custom.sql" \ 13 | --db-dump "file://$src_dir/test.dump.bz2" \ 14 | --tmp-path $src_dir/tmp 2>&1 15 | ) 16 | 17 | regex="Errors:[[:blank:]]*0" 18 | if [[ ! $output =~ $regex ]]; then 19 | test_passed=false 20 | fi 21 | 22 | artifacts_location=$( 23 | echo "$output" | grep "Artifacts (collected in " | awk -F"\"" '{print $2}' 24 | ) 25 | if [[ ! $(grep Linux "$artifacts_location/system_info.txt") =~ ^Linux ]]; then 26 | test_passed=false 27 | fi 28 | 29 | if [[ $test_passed ]]; then 30 | echo -e "\e[36mOK\e[39m" 31 | else 32 | >&2 echo -e "\e[31mFAILED\e[39m" 33 | >&2 echo -e "Output: $output" 34 | exit 1 35 | fi 36 | -------------------------------------------------------------------------------- /tests/nancy_run_localhost_simple_dump_with_index.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | realpath() { 4 | [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}" 5 | } 6 | 7 | src_dir=$(dirname $(dirname $(realpath "$0")))"/.circleci" 8 | if [ ! -d "$src_dir/tmp" ]; then 9 | mkdir "$src_dir/tmp" 10 | fi 11 | 12 | output=$( 13 | ${BASH_SOURCE%/*}/../nancy run \ 14 | --workload-custom-sql "file://$src_dir/custom.sql" \ 15 | --tmp-path ${src_dir}/tmp \ 16 | --db-dump "file://$src_dir/test.dump.bz2" \ 17 | --delta-sql-do "create index i_speedup on t1 using btree(val);" \ 18 | --delta-sql-undo "drop index i_speedup;" 2>&1 19 | ) 20 | 21 | regex="Errors:[[:blank:]]*0" 22 | if [[ $output =~ $regex ]]; then 23 | echo -e "\e[36mOK\e[39m" 24 | else 25 | >&2 echo -e "\e[31mFAILED\e[39m" 26 | >&2 echo -e "Output: $output" 27 | exit 1 28 | fi 29 | -------------------------------------------------------------------------------- /tests/nancy_run_localhost_simple_gz_dump.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | realpath() { 4 | [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}" 5 | } 6 | 7 | src_dir=$(dirname $(dirname $(realpath "$0")))"/.circleci" 8 | if [ ! -d "$src_dir/tmp" ]; then 9 | mkdir "$src_dir/tmp" 10 | fi 11 | 12 | output=$( 13 | ${BASH_SOURCE%/*}/../nancy run \ 14 | --workload-custom-sql "file://$src_dir/custom.sql" \ 15 | --db-dump "file://$src_dir/test.dump.gz" \ 16 | --tmp-path $src_dir/tmp 2>&1 17 | ) 18 | 19 | regex="Errors:[[:blank:]]*0" 20 | if [[ $output =~ $regex ]]; then 21 | echo -e "\e[36mOK\e[39m" 22 | else 23 | >&2 echo -e "\e[31mFAILED\e[39m" 24 | >&2 echo -e "Output: $output" 25 | exit 1 26 | fi 27 | -------------------------------------------------------------------------------- /tests/nancy_run_localhost_simple_sql_dump.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | realpath() { 4 | [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}" 5 | } 6 | 7 | src_dir=$(dirname $(dirname $(realpath "$0")))"/.circleci" 8 | if [ ! -d "$src_dir/tmp" ]; then 9 | mkdir "$src_dir/tmp" 10 | fi 11 | 12 | output=$( 13 | ${BASH_SOURCE%/*}/../nancy run \ 14 | --workload-custom-sql "file://$src_dir/custom.sql" \ 15 | --db-dump "file://$src_dir/test.dump.sql" \ 16 | --tmp-path $src_dir/tmp 2>&1 17 | ) 18 | 19 | regex="Errors:[[:blank:]]*0" 20 | if [[ $output =~ $regex ]]; then 21 | echo -e "\e[36mOK\e[39m" 22 | else 23 | >&2 echo -e "\e[31mFAILED\e[39m" 24 | >&2 echo -e "Output: $output" 25 | exit 1 26 | fi 27 | -------------------------------------------------------------------------------- /tests/nancy_run_localhost_wildcards.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | realpath() { 4 | [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}" 5 | } 6 | 7 | src_dir=$(dirname $(dirname $(realpath "$0")))"/.circleci" 8 | 9 | output=$( 10 | ${BASH_SOURCE%/*}/../nancy run \ 11 | --db-dump "create table t1 as select * from generate_series(1, 1000);" \ 12 | --workload-custom-sql "select count(*) from t1;" \ 13 | --tmp-path $src_dir/tmp 2>&1 14 | ) 15 | 16 | regex="Errors:[[:blank:]]*0" 17 | if [[ $output =~ $regex ]]; then 18 | echo -e "\e[36mOK\e[39m" 19 | else 20 | >&2 echo -e "\e[31mFAILED\e[39m" 21 | >&2 echo -e "Output: $output" 22 | exit 1 23 | fi 24 | 25 | -------------------------------------------------------------------------------- /tests/nancy_run_options_ddl_do+_undo-.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | read -r -d '' params <&1) 16 | 17 | if [[ $output =~ "must be also specified" ]]; then 18 | echo -e "\e[36mOK\e[39m" 19 | else 20 | >&2 echo -e "\e[31mFAILED\e[39m" 21 | >&2 echo -e "Output: $output" 22 | fi 23 | -------------------------------------------------------------------------------- /tests/nancy_run_options_ddl_do-_undo+.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | read -r -d '' params <&1) 16 | 17 | if [[ $output =~ "must be also specified" ]]; then 18 | echo -e "\e[36mOK\e[39m" 19 | else 20 | >&2 echo -e "\e[31mFAILED\e[39m" 21 | >&2 echo -e "Output: $output" 22 | fi 23 | -------------------------------------------------------------------------------- /tests/nancy_run_options_multi_workloads.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #read -r -d '' params <&1) 16 | 17 | #if [[ $output =~ "ERROR: 2 or more workload sources are given." ]]; then 18 | # echo -e "\e[36mOK\e[39m" 19 | #else 20 | # >&2 echo -e "\e[31mFAILED\e[39m" 21 | # >&2 echo -e "Output: $output" 22 | #fi 23 | -------------------------------------------------------------------------------- /tests/nancy_run_options_no_dump_snapshot.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | read -r -d '' params <&1) 14 | 15 | if [[ $output =~ "ERROR: The object (database) is not defined." ]]; then 16 | echo -e "\e[36mOK\e[39m" 17 | else 18 | >&2 echo -e "\e[31mFAILED\e[39m" 19 | >&2 echo -e "Output: $output" 20 | fi 21 | -------------------------------------------------------------------------------- /tests/nancy_run_options_no_instance_type.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | params="--run-on aws --aws-keypair-name awskey --aws-ssh-key-path \"/home/someuser/.ssh/awskey.pem\"" 4 | output=$(${BASH_SOURCE%/*}/../nancy_run.sh $params 2>&1) 5 | 6 | if [[ $output =~ "ERROR: AWS EC2 Instance type is not specified." ]]; then 7 | echo -e "\e[36mOK\e[39m" 8 | exit 0 9 | else 10 | >&2 echo -e "\e[31mFAILED\e[39m" 11 | >&2 echo -e "Output: $output" 12 | exit 1 13 | fi 14 | -------------------------------------------------------------------------------- /tests/nancy_run_too_many_objects.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | export PATH=$PATH:${BASH_SOURCE%/*}/.. 4 | 5 | output=$(nancy run --db-dump '--' --db-local-pgdata file:///z --workload-custom-sql '--' 2>&1) 6 | 7 | if [[ $output =~ "ERROR: Too many objects (ways to get PGDATA) are specified. Please specify only one." ]]; then 8 | echo -e "\e[36mOK\e[39m" 9 | else 10 | >&2 echo -e "\e[31mFAILED\e[39m" 11 | >&2 echo -e "Output: $output" 12 | exit 1 13 | fi 14 | -------------------------------------------------------------------------------- /tests/nancy_run_too_many_workloads.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | export PATH=$PATH:${BASH_SOURCE%/*}/.. 4 | 5 | output=$(nancy run --db-dump '--' --workload-custom-sql '--' --workload-pgbench '-t 1' 2>&1) 6 | 7 | if [[ $output =~ "ERROR: Too many kinds of workload are specified. Please specify only one." ]]; then 8 | echo -e "\e[36mOK\e[39m" 9 | else 10 | >&2 echo -e "\e[31mFAILED\e[39m" 11 | >&2 echo -e "Output: $output" 12 | exit 1 13 | fi 14 | 15 | -------------------------------------------------------------------------------- /tools/meminfo.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | MACHINE_HOME="/machine_home" 4 | 5 | echo "time;MemTotal,kB;MemFree,kB;Buffers,kB;Active(file),kB;Inactive(file),kB;SwapFree,kB;Shmem,kB;Slab,kB;PageTables,kB" > $MACHINE_HOME/meminfo.run.csv 6 | while true; do 7 | dt=$(date --rfc-3339=ns) 8 | echo "${dt}" >> $MACHINE_HOME/meminfo.run.log 9 | cat /proc/meminfo > $MACHINE_HOME/meminfo.log 10 | cat $MACHINE_HOME/meminfo.log >> $MACHINE_HOME/meminfo.run.log 11 | echo "" >> $MACHINE_HOME/meminfo.run.log 12 | meminfo="${dt}" 13 | for param in "MemTotal" "MemFree" "Buffers" "Active\(file\)" "Inactive\(file\)" "SwapFree" "Shmem" "Slab" "PageTables" 14 | do 15 | paramValue=$(bash -c "cat ${MACHINE_HOME}/meminfo.log | grep -P '^${param}: +.+ .+' | awk '{print \$2}'") 16 | meminfo="${meminfo};${paramValue}" 17 | done 18 | echo -e "${meminfo}" >> $MACHINE_HOME/meminfo.run.csv 19 | sleep $FREQ 20 | done; -------------------------------------------------------------------------------- /tools/parse_yaml.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ####################################### 4 | # Parse simple YAML file 5 | # Globals: 6 | # None 7 | # Arguments: 8 | # (text) path to yaml file 9 | # Returns: 10 | # None 11 | ####################################### 12 | function parse_yaml() { 13 | local yaml_file=$1 14 | local prefix=$2 15 | local s 16 | local w 17 | local fs 18 | 19 | s='[[:space:]]*' 20 | w='[a-zA-Z0-9_.-]*' 21 | fs="$(echo @|tr @ '\034')" 22 | 23 | ( 24 | sed -ne '/^--/s|--||g; s|\"|\\\"|g; s/\s*$//g;' \ 25 | -e "/#.*[\"\']/!s| #.*||g; /^#/s|#.*||g;" \ 26 | -e "s|^\($s\)\($w\)$s:$s\"\(.*\)\"$s\$|\1$fs\2$fs\3|p" \ 27 | -e "s|^\($s\)\($w\)$s[:-]$s\(.*\)$s\$|\1$fs\2$fs\3|p" | 28 | awk -F"$fs" '{ 29 | indent = length($1)/2; 30 | if (length($2) == 0) { conj[indent]="+";} else {conj[indent]="";} 31 | vname[indent] = $2; 32 | for (i in vname) {if (i > indent) {delete vname[i]}} 33 | if (length($3) > 0) { 34 | vn=""; for (i=0; i&1 > /dev/null -------------------------------------------------------------------------------- /tools/unittest/parse_yml.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | source ${BASH_SOURCE%/*}/../parse_yaml.sh "${BASH_SOURCE%/*}/../../.circleci/run.yml" "yml_" 4 | 5 | i=0 6 | while : ; do 7 | var_name_config="yml_run_"$i"_delta_config" 8 | delta_config=$(eval echo \$$var_name_config) 9 | delta_config=$(echo $delta_config | tr ";" "\n") 10 | var_name_ddl_do="yml_run_"$i"_delta_ddl_do" 11 | delta_ddl_do=$(eval echo \$$var_name_ddl_do) 12 | var_name_ddl_undo="yml_run_"$i"_delta_ddl_undo" 13 | delta_ddl_undo=$(eval echo \$$var_name_ddl_undo) 14 | [[ -z $delta_config ]] && [[ -z $delta_ddl_do ]] && [[ -z $delta_ddl_undo ]] && break; 15 | let j=$i*3 16 | RUNS[$j]="$delta_config" 17 | [[ -z $delta_config ]] && RUNS[$j]="" 18 | RUNS[$j+1]="$delta_ddl_do" 19 | [[ -z $delta_ddl_do ]] && RUNS[$j+1]="" 20 | RUNS[$j+2]="$delta_ddl_undo" 21 | [[ -z $delta_ddl_undo ]] && RUNS[$j+2]="" 22 | let i=i+1 23 | done 24 | # validate runs config 25 | runs_count=${#RUNS[*]} 26 | let runs_count=runs_count/3 27 | 28 | if [[ "$runs_count" -eq "3" ]] ; then 29 | echo -e "\e[36mOK\e[39m" 30 | else 31 | >&2 echo -e "\e[31mFAILED\e[39m" 32 | echo "YML runs config count: $runs_count" 33 | exit 1 34 | fi 35 | --------------------------------------------------------------------------------