DB Architecture & Conventions #1
ctapobep
started this conversation in
Conventions & Approaches
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
Naming
fk_table_a__table_b
(this is a BEM-like convention where the separator between 2 entities is double underscore)idx_table_name__col_name
, Unique constraint:uq_table_name__col_name
. Composite indices that include multiple columns are more challenging. Maybe:idx_table_name__col_name1__col_name2
oridx_table_name__colname1_colname2
?Handlig CLOBs
Again, on the off chance we have to support Oracle some day: CLOBs cannot be 8000 symbols. So for CLOB fields we need to add Java logic to add spaces to get to 8001. There's a bug in Oracle JDBC Driver (?) which confuses the encoding and suddenly starts to use UTF16 for 8000 CLOBs which screws everything up.
Indices
Most Foreign Keys should have indices. Otherwise some JOINs will be slower and DELETEs too (when deleting a record DB has to check if it's referenced by some FKs).
If you suspect a full table scan ('seq scan' in terms of Postgres), use this to find which table is scanned:
Sorting by ID
Usually, when DB was just created, selecting records w/o sorting returns them in the same order they were inserted. But in PG this isn't always the case. So if the order is important, you must add
order by id
explicitly.Cascades
(More research may be needed) It seems like DBs handle "on cascade=delete" just fine, so prefer those cascades instead of Hibernate's cascades. DB cascades should be faster. Of course these should be used with cautious - only for cases when child object can't exist without the parent.
Transactions
We mostly work in Snapshot Isolation level. Java and PG call this isolation level Repeatable Read, but in reality in PG it corresponds to Snapshot level. Snapshot level is activated when connection is created by C3P0 DB Pool, see
DbConnectionCustomizer.java
.Repeatable Read has problems with race conditions that can result in dirty writes (when we override the same row in parallel transactions). While on Snapshot level one of the transactions will get:
How to use Snapshot level:
Explicitly changing Isolation Level in code
It's possible that 2 parallel transactions update completely irrelevant data. Getting an error in such situations is very unfortunate. If we know what we're doing, we can explicitly lower the isolation level, at least for one of the transactions - at least this way only 50% of cases will result in the error.
Caution
We should prefer doing this with Spring's
@Transactional
as it reverts the isolation level back to the original state after the tx completes. Otherwise, do it in try-finally block. If at some point we forget to revert the isolation level back, the results will be disastrous - we'll gradually turn all connections into Read Committed without realizing it.Beta Was this translation helpful? Give feedback.
All reactions