Skip to content

Commit 96a5a45

Browse files
committed
docs(dev): database-related information
Signed-off-by: Mike Fiedler <[email protected]>
1 parent 5c8c415 commit 96a5a45

File tree

2 files changed

+87
-4
lines changed

2 files changed

+87
-4
lines changed

docs/dev/development/database-migrations.rst

+71-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1+
###################
12
Database migrations
2-
===================
3+
###################
34

45
Modifying database schemata will need database migrations (even for adding and
56
removing tables). To autogenerate migrations::
@@ -9,8 +10,9 @@ removing tables). To autogenerate migrations::
910
Verify your migration was generated by looking at the output from the command
1011
above:
1112

12-
``Generating /opt/warehouse/src/warehouse/migrations/versions/390811c1c\
13-
dbe_.py ... done``
13+
.. code-block:: console
14+
15+
Generating /opt/warehouse/src/warehouse/migrations/versions/390811c1cdbe_.py ... done
1416
1517
Then migrate and test your migration::
1618

@@ -24,6 +26,11 @@ This makes it more difficult to make breaking changes, since you must phase
2426
them in over time. See :ref:`destructive-migrations` for tips on doing
2527
migrations that involve column deletions or renames.
2628

29+
.. _migration-timeouts:
30+
31+
Migration Timeouts
32+
==================
33+
2734
To help protect against an accidentally long running migration from taking down
2835
PyPI, by default a migration will timeout if it is waiting more than 4s to
2936
acquire a lock, or if any individual statement takes more than 5s.
@@ -56,7 +63,7 @@ environment like PyPI, there is related reading available at:
5663
.. _destructive-migrations:
5764

5865
Destructive migrations
59-
----------------------
66+
======================
6067

6168
.. warning::
6269

@@ -104,3 +111,63 @@ a data migration. To rename a column:
104111

105112
In total, this requires three separate migrations: one to add the new column,
106113
one to backfill to it, and a third to remove the old column.
114+
115+
Creating Indexes
116+
================
117+
118+
Indexes should be declared as part of SQLAlchemy Table definitions,
119+
often under the ``__table_args__`` attribute.
120+
Once declared, auto-generating a migration will create the index for alembic.
121+
122+
See more in index definition in
123+
`SQLAlchemy documentation <https://docs.sqlalchemy.org/en/20/core/constraints.html#schema-indexes>`_.
124+
125+
Since index creation will often take longer than a few seconds
126+
for tables that are large or active,
127+
it is recommended to create indexes concurrently.
128+
129+
To create an index concurrently, adding ``postgresql_concurrently=True``
130+
to the index definition is incompatible with our deployment migration process
131+
as it runs in a transaction, and concurrent index creation requires a separate transaction.
132+
133+
Instead, manually update the migration to start a separate transaction.
134+
135+
After auto-generating the new migration, update the migration to create the index concurrently.
136+
Here's an example of an migration for a definition of ``Index("tbl1_column1_idx", "column1")``
137+
that was auto-generated, and manually updated to create the index concurrently:
138+
139+
.. code-block:: diff
140+
141+
def upgrade():
142+
- op.create_index(
143+
- "tbl1_column1_idx",
144+
- "tbl1",
145+
- ["column1"],
146+
- unique=False,
147+
- )
148+
+ # CREATE INDEX CONCURRENTLY cannot happen inside a transaction. We'll close
149+
+ # our transaction here and issue the statement.
150+
+ op.get_bind().commit()
151+
+ with op.get_context().autocommit_block():
152+
+ op.create_index(
153+
+ "tbl1_column1_idx",
154+
+ "tbl1",
155+
+ ["column1"],
156+
+ unique=False,
157+
+ if_not_exists=True
158+
+ postgresql_concurrently=True,
159+
+ )
160+
161+
The original ``op.create_index()`` call is indented under a context manager,
162+
and the keyword args ``if_not_exists=True`` and ``postgresql_concurrently=True``
163+
are added to the call.
164+
165+
Leave the generated ``downgrade()`` function as normal.
166+
167+
If the index creation is likely to continue to take longer than a few seconds,
168+
and most indexes on existing tables in use are likely to take longer than a few seconds,
169+
it is recommended to modify the migration to increase the statement timeout
170+
as described in :ref:`migration-timeouts`.
171+
172+
Another option is to share the SQL statement to create the index concurrently
173+
on the Pull Request, and have a maintainer run the statement manually.

docs/dev/development/development-database.rst

+16
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,19 @@ Now commit the result::
3030
git checkout -b update_dev_db_dump && \
3131
git add dev/example.sql.xz && \
3232
git commit -m "Update development database dump"
33+
34+
35+
Connecting to the Development Database
36+
======================================
37+
38+
To connect to the development database, use the following command::
39+
40+
make dbshell
41+
42+
This will spawn a one-time container that connects to the database,
43+
and opens a shell for you to interact with it.
44+
45+
If you want to use another tool from your host machine,
46+
you can connect to the database using a connection string, like this::
47+
48+
pgcli postgresql://postgres@localhost:5433/warehouse

0 commit comments

Comments
 (0)