Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement schema squashing #3253

Merged
merged 10 commits into from
May 20, 2020
Merged

Implement schema squashing #3253

merged 10 commits into from
May 20, 2020

Conversation

aleksejuber
Copy link
Contributor

What changed?

For incremental schema, it is now possible to take a shortcut from one version to another without applying incremental changes one by one.
The directory name should be in format s<from_ver>-<to_ver>, where

  • <to_ver> must be greater than <from_ver>
  • <to_ver> must exist in incremental schema steps, i.e. a directory with valid manifest named v_<to_ver> must exist
  • <from_ver> must either exist in incremental schema steps, or be equal to initial version 0.0

Schema tool will automatically select the path with least steps.

Squashed shortcut schema from version 0.0 to 0.23 included. This particular schema version is selected since it's on the tip of latest 0.11 Cadence release.

Why?

For Cassandra instances with large replication factors and latency schema statements might take up to a second for a trivial operation such as column creation. Given that current version on tip of master is 0.27, the bootstrap time adds up and will grow with each schema update.

Applying goal-state schema would only create 30+ entities and would run up to 4x times faster on Cassandra setups above.

Applying schema.cql is an option for a new installation, but prevents further incremental upgrades.

How did you test it?

To measure speed improvements, application times for both schema and every incremental version is now logged. Tested by playing back incremental updates up to version 0.27 on docker instance

Time improvements

Before the change

cadence_1      | 2020/05/11 20:35:15 Schema updated from 0.0 to 0.1, elapsed 2.247461928s
cadence_1      | 2020/05/11 20:35:17 Schema updated from 0.1 to 0.2, elapsed 1.631742425s
cadence_1      | 2020/05/11 20:35:18 Schema updated from 0.2 to 0.3, elapsed 836.043275ms
cadence_1      | 2020/05/11 20:35:19 Schema updated from 0.3 to 0.4, elapsed 633.861512ms
cadence_1      | 2020/05/11 20:35:19 Schema updated from 0.4 to 0.5, elapsed 394.238516ms
cadence_1      | 2020/05/11 20:35:20 Schema updated from 0.5 to 0.6, elapsed 1.130838727s
cadence_1      | 2020/05/11 20:35:24 Schema updated from 0.6 to 0.7, elapsed 3.86523542s
cadence_1      | 2020/05/11 20:35:24 Schema updated from 0.7 to 0.8, elapsed 303.648524ms
cadence_1      | 2020/05/11 20:35:25 Schema updated from 0.8 to 0.9, elapsed 457.736671ms
cadence_1      | 2020/05/11 20:35:25 Schema updated from 0.9 to 0.10, elapsed 436.88099ms
cadence_1      | 2020/05/11 20:35:28 Schema updated from 0.10 to 0.11, elapsed 2.453376415s
cadence_1      | 2020/05/11 20:35:31 Schema updated from 0.11 to 0.12, elapsed 3.061781143s
cadence_1      | 2020/05/11 20:35:32 Schema updated from 0.12 to 0.13, elapsed 1.82323551s
cadence_1      | 2020/05/11 20:35:33 Schema updated from 0.13 to 0.14, elapsed 336.098623ms
cadence_1      | 2020/05/11 20:35:34 Schema updated from 0.14 to 0.15, elapsed 799.870505ms
cadence_1      | 2020/05/11 20:35:34 Schema updated from 0.15 to 0.16, elapsed 192.859672ms
cadence_1      | 2020/05/11 20:35:34 Schema updated from 0.16 to 0.17, elapsed 378.112309ms
cadence_1      | 2020/05/11 20:35:35 Schema updated from 0.17 to 0.18, elapsed 387.9124ms
cadence_1      | 2020/05/11 20:35:36 Schema updated from 0.18 to 0.19, elapsed 1.129843878s
cadence_1      | 2020/05/11 20:35:36 Schema updated from 0.19 to 0.20, elapsed 195.834643ms
cadence_1      | 2020/05/11 20:35:36 Schema updated from 0.20 to 0.21, elapsed 178.099493ms
cadence_1      | 2020/05/11 20:35:37 Schema updated from 0.21 to 0.22, elapsed 902.453475ms
cadence_1      | 2020/05/11 20:35:37 Schema updated from 0.22 to 0.23, elapsed 531.753091ms
cadence_1      | 2020/05/11 20:35:38 Schema updated from 0.23 to 0.24, elapsed 181.113603ms
cadence_1      | 2020/05/11 20:35:38 Schema updated from 0.24 to 0.25, elapsed 160.556925ms
cadence_1      | 2020/05/11 20:35:38 Schema updated from 0.25 to 0.26, elapsed 531.831506ms
cadence_1      | 2020/05/11 20:35:38 Schema updated from 0.26 to 0.27, elapsed 110.09224ms
cadence_1      | 2020/05/11 20:35:38 All schema changes completed in 25.296508226s
After the change
cadence_1      | 2020/05/11 22:37:38 Schema updated from 0.0 to 0.23, elapsed 4.242590367s
cadence_1      | 2020/05/11 22:37:39 Schema updated from 0.23 to 0.24, elapsed 303.520763ms
cadence_1      | 2020/05/11 22:37:39 Schema updated from 0.24 to 0.25, elapsed 227.529843ms
cadence_1      | 2020/05/11 22:37:39 Schema updated from 0.25 to 0.26, elapsed 741.045226ms
cadence_1      | 2020/05/11 22:37:40 Schema updated from 0.26 to 0.27, elapsed 164.768217ms
cadence_1      | 2020/05/11 22:37:40 All schema changes completed in 5.679644717s

Data validitiy

Before the change
root@1370b14fd06a:/# cqlsh -e "DESC KEYSPACE cadence"|md5sum
bd705d28afcfe8b5a207a905af16f9e1  -
root@1370b14fd06a:/# cqlsh -k cadence --no-color -e "SELECT * FROM domains;"|md5sum
6672f72e06d45d845df8aa736825f11d  -
root@1370b14fd06a:/# cqlsh -k cadence --no-color -e "SELECT * FROM domains_by_name_v2;"|md5sum
69dcf3ee18d67a066915dd371e622ac3  -
After the change
root@21133ee99c79:/# cqlsh -e "DESC KEYSPACE cadence"|md5sum
bd705d28afcfe8b5a207a905af16f9e1  -

root@21133ee99c79:/# cqlsh -k cadence --no-color -e "SELECT * FROM domains;"|md5sum
6672f72e06d45d845df8aa736825f11d  -

root@21133ee99c79:/# cqlsh -k cadence --no-color -e "SELECT * FROM domains_by_name_v2;"|md5sum
69dcf3ee18d67a066915dd371e622ac3  -

Potential risks

As with any other schema change, there are risks involved. One of the concerns is mismatching schemas in schema.cql for 0.11 Cadence version (v0.23 Cassandra schema) and playing back the incremental changes. Some are minor, such as column ordering, but there is a missing events table and mismatching data type for a column.

However, the tests above show that shortcut schema is identical to one produced by playing incremental changes back.

@coveralls
Copy link

coveralls commented May 12, 2020

Coverage Status

Coverage decreased (-0.1%) to 68.995% when pulling 25b7cc1 on schema_squashing into c4c485e on master.

@meiliang86 meiliang86 requested a review from a team May 12, 2020 16:30
@emrahs
Copy link
Contributor

emrahs commented May 12, 2020

@aleksejuber PR looks pretty good to me. I just left a minor comment. Besides that, have you considered automating your md5sum test in as an integration test (possibly in tools/common/schema/test/updatetest.go)? I think it would be good to have it so that we don't need to reinvent a manual way to verify each new squash in the future. It'd also prevent inconsistencies in case a contributor modifies these CQL files for some reason.

@aleksejuber
Copy link
Contributor Author

. Besides that, have you considered automating your md5sum test in as an integration test (possibly in tools/common/schema/test/updatetest.go)?

This is a very good point, the integration test would surely benefit here to ensure initial data/schema consistency. I believe the check can be done without modifying the Go code, using modified schema initialisation bash scripts, as in

  1. List all the shortcut directories to determine the end version and rename/move them out
  2. Apply versions as usual, but take snapshots after every end version
  3. On by one move the shortcut directories back, remove keyspace, init version 0.0, replay up to the end version, compare schemas, and remove the shortcut

This way we will run same commands as the schema init scripts and avoid missing something out in test setup.

In your opinion, should the integration tests be included in this PR or create a separate one for this issue?

@emrahs
Copy link
Contributor

emrahs commented May 13, 2020

In your opinion, should the integration tests be included in this PR or create a separate one for this issue?

I'm OK with either way. Regarding how we implement the tests, I'd prefer having those in tools/updatetest.go for consistency with other tests and to ensure they run together.

In order to evaluate the efficiency of schema updates, log the time it
takes to apply every incremental schema change, as well as all the
schema update time overall.
Refactor the tooling to separate the filesystem access and filtering of
versioned directory names.
The directory filtering routine should accept the directories in the
form of 'sx.x-y.y' which contain batched statements for version
shortcuts from version x.x to version y.y

If the directories are found and are within range, use the shortcuts to
reduce the number of statements executed on setup.
Use "gonum.org/v1/gonum/graph" graph library and its' impementation of
the Dijkstra algorithm to find the shortest path from verion X to Y,
when version shortcuts are present in the schema directory.
Enable the path search algorithm in the schema update directory search
routine.
Add a version shortcut from version 0.0 to 0.23 (the active
schema version for Cadence version 0.11)
As suggested, split the shortcut statements in two groups: first
with inserts only, second with INSERT statements for seed data.
 - Use `.ElementsMatch` to compare two sets of tables
 - Use `.NoError` instead of `.Nil` for error asserts
 - Use `.Empty` instead of `Equal(0, len(...))`
As shortcuts for schema changes were introduced, a new integration
test is required to ensure schema integrity.

Test workflow is:

 - Enumerate all shortcuts and select target versions
 - Using incremental schema changes, apply each target version in
order and export the schema using `cqlsh`
 - For each shortcut directory, copy it over, apply target version,
call `cqlsh` to export the schema and compare it to the schema
generated from incremental changes. On success, remove the
directory.

Testing:
Tests pass with current schema

After modifying the shortcut schema manually, test fails with

```
Diff:
--- Expected
+++ Actual
@@ -518,3 +518,3 @@
     data blob,
-    data_encoding text,
+    data_encoding blob,
     data_version int,
```

as expected.

Add cqlsh to the testing docker

Since tests are using cqlsh to export schema, add the cqlsh to the testing container
@aleksejuber aleksejuber merged commit 72f9705 into master May 20, 2020
@aleksejuber aleksejuber deleted the schema_squashing branch May 20, 2020 18:42
yux0 pushed a commit to yux0/cadence that referenced this pull request May 4, 2021
* Add schema application timing log

In order to evaluate the efficiency of schema updates, log the time it
takes to apply every incremental schema change, as well as all the
schema update time overall.

* Add support for squashed versions

The directory filtering routine should accept the directories in the
form of 'sx.x-y.y' which contain batched statements for version
shortcuts from version x.x to version y.y

If the directories are found and are within range, use the shortcuts to
reduce the number of statements executed on setup.

* Split directory reads and filtering

Refactor the tooling to separate the filesystem access and filtering of
versioned directory names.

* Implement shortest version upgrade path search

Use "gonum.org/v1/gonum/graph" graph library and its' impementation of
the Dijkstra algorithm to find the shortest path from verion X to Y,
when version shortcuts are present in the schema directory.

* Use the path search to apply schema changes

Enable the path search algorithm in the schema update directory search
routine.

* Add squashed 0.23 version

Add a version shortcut from version 0.0 to 0.23 (the active
schema version for Cadence version 0.11)

* Separate schema statements from inserts

As suggested, split the shortcut statements in two groups: first
with inserts only, second with INSERT statements for seed data.

* Lint schema test base

 - Use `.ElementsMatch` to compare two sets of tables
 - Use `.NoError` instead of `.Nil` for error asserts
 - Use `.Empty` instead of `Equal(0, len(...))`

* Add integration test for schema shortcuts

As shortcuts for schema changes were introduced, a new integration
test is required to ensure schema integrity.

Test workflow is:

 - Enumerate all shortcuts and select target versions
 - Using incremental schema changes, apply each target version in
order and export the schema using `cqlsh`
 - For each shortcut directory, copy it over, apply target version,
call `cqlsh` to export the schema and compare it to the schema
generated from incremental changes. On success, remove the
directory.

Testing:
Tests pass with current schema

After modifying the shortcut schema manually, test fails with

```
Diff:
--- Expected
+++ Actual
@@ -518,3 +518,3 @@
     data blob,
-    data_encoding text,
+    data_encoding blob,
     data_version int,
```

as expected.

Add cqlsh to the testing docker

Since tests are using cqlsh to export schema, add the cqlsh to the testing container
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants