Asp.Net Core Identity + EF Core + CockroachDb = very slow

Viewed 725

I want to use CockroachDb with Asp.Net Core Identity. Cockroach uses Postgres' wire protocol, so Npgsql.EntityFrameworkCore.PostgreSQL package works with Cockroach as well.

Simply adding all the necessary services, generating migration and applying it doesn't work, because generated migration uses NpgsqlValueGenerationStrategy.IdentityByDefaultColumn, which results in columns with GENERATED BY DEFAULT AS IDENTITY, which is not supported by Cockroach. So I changed NpgsqlValueGenerationStrategy to SerialColumn in all the generated migration files (migration, designer, model snapshot). After this change applying migration works, but another error arises when calling UserManager.AddClaim. Overflow exception. So I figured this is because Cockroach for SERIAL columns by default does not use sequences, but instead generates unique numbers based on current timestamp and node id, which results in some pretty huge numbers. Cockroach provides a way to overwrite the behavior of SERIAL keyword for current session by executing SET experimental_serial_normalization = sql_sequence. So I dropped all the tables and applied migration again, but before doing it added code, which executes above mentioned command, to AppDbContext's constructor. After applying migration this code can be removed, because it is not needed anymore.

Doing all these things makes Identity work with CockroachDb, but it is super slow. Creating new user takes ~4 seconds. Adding new claim - roughly the same. Compared to PostgreSQL's ~1 second.

Using EF Core with Cockroach outside of Identity is slow, but not unreasonably so. But combining EF Core and Cockroach with Identity makes performance unacceptable.

What can be the problem? Maybe changing all these things to make Identity work with Cockroach messes it up somehow? Functionality-wise everything works fine.

2 Answers

The sql_sequence setting is expected to be slower, since it adds a lot of coordination between the different nodes in the cluster to make sure the sequence increases by one incrementally.

Here is an excerpt from the release notes for this feature.

CockroachDB now supports two experimental compatibility modes with how PostgreSQL handles SERIAL and sequences, to ease reuse of 3rd party frameworks or apps developed for PostgreSQL. These modes can be enabled with the experimental_serial_normalization session variable (per client) and sql.defaults.serial_normalization cluster setting (cluster-wide). The first mode, virtual_sequence, enables compatibility with many applications using SERIAL with maximum performance and scalability. The second mode, sql_sequence, enables maximum PostgreSQL compatibility but uses regular SQL sequences and is thus subject to performance constraints.

I think the ideal would be to not use sql_sequence and things should be fixed so the numbers that are generated don't overflow. This could be fixed in one of two ways:

ASPNET Identity will allow you to use a GUID as the Id. If you just change that, the rest will work without any issue and will perform accordingly

Related