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

KEYCLOAK-3988: Multiple missing indexes on FKs. #3557

Merged
merged 1 commit into from
May 23, 2017
Merged

KEYCLOAK-3988: Multiple missing indexes on FKs. #3557

merged 1 commit into from
May 23, 2017

Conversation

glavoie
Copy link
Contributor

@glavoie glavoie commented Nov 28, 2016

During performance testing with a large number of realms, we found out that many indexes are missing for FKs, at least on an Oracle database. As indexes are not created automatically on FKs at least on Oracle, MSSQL and PostgreSQL.

@hmlnarik
Copy link
Contributor

👍

@stianst stianst added the 3.x label Nov 29, 2016
@@ -22,4 +22,46 @@
<customChange class="org.keycloak.connections.jpa.updater.liquibase.custom.MigrateUserFedToComponent"/>
</changeSet>

<changeSet author="glavoie@gmail.com" id="2.4.1.index">
<preConditions onSqlOutput="TEST" onFail="MARK_RAN">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's with the pre-coniditions? Would be better to just add same indexes for all dbs

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They were added after comments from @hmlnarik here: glavoie@7bb44b7

@stianst
Copy link
Contributor

stianst commented Mar 7, 2017

@hmlnarik is the preconditions for the indexes really needed? Would the db automatically create the index if one is manually created?

@hmlnarik
Copy link
Contributor

hmlnarik commented Mar 7, 2017

We can leave them out for the moment and add preconditions for not adding the indices if there would be an issue with duplicate indices. I'm more inclined to add indices only for databases we have tested do not create them automatically, but I'll won't be against accepting this PR without the preconditions.

The important part here is that thanks to these changes, performance on the tested databases improves, so IMHO it should certainly get in.

We'll only need to put the changes into a new changeset as this did not get into 2.4.1.

@stianst
Copy link
Contributor

stianst commented Mar 8, 2017

Ok, so I guess it makes more sense to have the pre-condition. Was looking the Liquibase docs and onSqlOutput isn't there. Also, why would it mark as ran on an error? Shouldn't it rather halt?

Does MySQL and MariaDB create these indexes automatically?

@glavoie
Copy link
Contributor Author

glavoie commented Apr 13, 2017

We started doing more performance testing for different scenarios and encountered new issues. When doing concurrent client deletion (and it would likely appear with different operations), we started to see "java.sql.SQLException: ORA-00060: deadlock detected while waiting for resource" caused by missing indices on other FKs (again on Oracle). When an index is missing, Oracle may lock a whole table rather than just the concerned rows for an operation. There are currently 81 FKs to cover.

Here's some information regarding the Oracle issue: https://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:3932525800346405986

We also found a missing primary key in COMPOSITE_ROLE that would ensure integrity and add an implicit index.

Should I modify the current PR with all the suggested changes and attach it to Keycloak's next version Liquibase changelog file?

Also, should I adjust the pre-condition to create indices on all RDBMS, but exclude MySQL and MariaDB, or remove it completely? I think it is better to create "extra" indices than have large performance/database issues for FKs. The exclusion for those 2 RDBMS might also be unnecessary is the documentation mentions that they will create an index only if it is missing, and that an implicit index might be dropped if an explicit index is created on a FK:

https://dev.mysql.com/doc/refman/5.7/en/create-table-foreign-keys.html

Such an index is created on the referencing table automatically if it does not exist. This index might be silently dropped later, if you create another index that can be used to enforce the foreign key constraint.

@stianst
Copy link
Contributor

stianst commented Apr 19, 2017

+1 To simply updating this PR with the new changes and changelog file

I reckon indexes should just be created for all dbs as it seems MySQL will clean it up automatically. @hmlnarik what do you think?

@hmlnarik
Copy link
Contributor

Yes, it seems MySQL started behaving, and the other supported databases are treating the indices in expected manner. Hence +1 on removing the constraint.

@glavoie
Copy link
Contributor Author

glavoie commented Apr 19, 2017

Just pushed a new version of the PR with all the missing indices. Removed the condition as well.

@stianst stianst removed the 3.x label Apr 21, 2017
@glavoie
Copy link
Contributor Author

glavoie commented May 4, 2017

Any comment/review?

@stianst
Copy link
Contributor

stianst commented May 5, 2017

Sorry for the delay. Could you bump changelog versions to 3.2? We'll try to get this included in 3.2.

@hmlnarik can you review please?
@pdrozd can we somehow run the db matrix on CI with this PR before merging?

@glavoie
Copy link
Contributor Author

glavoie commented May 5, 2017

PR updated.

@pdrozd
Copy link
Contributor

pdrozd commented May 11, 2017

@stianst DB matrix on CI passed successfully

@stianst
Copy link
Contributor

stianst commented May 11, 2017

@pdrozd Awezome! Thanks for checking it out.

@glavoie @hmlnarik is away for a few days, but I'll have him review it again once he's back.

Copy link
Contributor

@hmlnarik hmlnarik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for delay, I was away. I've gone through the changes and there are quite a few indices defined that are already leftmost part of a composite index. These composite indices are used even for queries that match only on (the leftmost) part of the index so declaring them as new would be redundant. I hope I did not oversee any other duplication and after removing the indicated indices, this PR would be good to go from my point of view.

<column name="ASSOCIATED_POLICY_ID" type="VARCHAR(36)"/>
</createIndex>
<createIndex indexName="IDX_ASSOC_POL_POL_ID" tableName="ASSOCIATED_POLICY">
<column name="POLICY_ID" type="VARCHAR(36)"/>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This index is unnecessary because there is already an index for primary key on ASSOCIATED_POLICY(POLICY_ID, ASSOCIATED_POLICY_ID) from here. Please remove.

<column name="REALM_ID" type="VARCHAR(36)"/>
</createIndex>
<createIndex indexName="IDX_CLIENT_REALM" tableName="CLIENT">
<column name="REALM_ID" type="VARCHAR(36)"/>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This index is unnecessary because there is already a unique index on CLIENT(REALM_ID, NAME) from here. Please remove.

<column name="CLIENT_TEMPLATE_ID" type="VARCHAR(36)"/>
</createIndex>
<createIndex indexName="IDX_CLIENT_ATTR_CLIENT" tableName="CLIENT_ATTRIBUTES">
<column name="CLIENT_ID" type="VARCHAR(36)"/>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This index is unnecessary because there is already an index for primary key on CLIENT_ATTRIBUTES(CLIENT_ID, NAME) from here. Please remove.

</createIndex>
<createIndex indexName="IDX_CLI_ID_PRV_MAP_ID_PRV" tableName="CLIENT_IDENTITY_PROV_MAPPING">
<column name="IDENTITY_PROVIDER_ID" type="VARCHAR(36)"/>
</createIndex>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This index is unnecessary because there is already a unique index on CLIENT_IDENTITY_PROV_MAPPING(IDENTITY_PROVIDER_ID, CLIENT_ID) from here. Please remove.

</createIndex>
<createIndex indexName="IDX_CLIENT_NODE_REG_CLIENT" tableName="CLIENT_NODE_REGISTRATIONS">
<column name="CLIENT_ID" type="VARCHAR(36)"/>
</createIndex>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This index is unnecessary because there is already an index for primary key on CLIENT_NODE_REGISTRATIONS(CLIENT_ID, NAME) from here. Please remove.

<column name="RESOURCE_SERVER_ID" type="VARCHAR(36)"/>
</createIndex>
<createIndex indexName="IDX_SCOPE_MAPPING_CLIENT" tableName="SCOPE_MAPPING">
<column name="CLIENT_ID" type="VARCHAR(36)"/>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This index is unnecessary because there is already an index for primary key on SCOPE_MAPPING(CLIENT_ID, ROLE_ID) named constraint_81. Please remove.

<column name="POLICY_ID" type="VARCHAR(36)"/>
</createIndex>
<createIndex indexName="IDX_SCOPE_POLICY_SCOPE" tableName="SCOPE_POLICY">
<column name="SCOPE_ID" type="VARCHAR(36)"/>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This index is unnecessary because there is already an index for primary key on SCOPE_POLICY(SCOPE_ID, POLICY_ID) named constraint_farsrsps. Please remove.

<column name="SCOPE_ID" type="VARCHAR(36)"/>
</createIndex>
<createIndex indexName="IDX_TEMPL_SCOPE_MAPP_TEMPL" tableName="TEMPLATE_SCOPE_MAPPING">
<column name="TEMPLATE_ID" type="VARCHAR(36)"/>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This index is unnecessary because there is already an index for primary key on TEMPLATE_SCOPE_MAPPING(TEMPLATE_ID, ROLE_ID) named pk_template_scope. Please remove.

<column name="ROLE_ID" type="VARCHAR(36)"/>
</createIndex>
<createIndex indexName="IDX_USR_FED_CFG_USER_FED_PRV" tableName="USER_FEDERATION_CONFIG">
<column name="USER_FEDERATION_PROVIDER_ID" type="VARCHAR(36)"/>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This index is unnecessary because there is already an index for primary key on USER_FEDERATION_CONFIG(USER_FEDERATION_PROVIDER_ID, NAME) named constraint_f9. Please remove.

<column name="REALM_ID" type="VARCHAR(36)"/>
</createIndex>
<createIndex indexName="IDX_USR_FD_MAP_CFG_USR_FD_MAP" tableName="USER_FEDERATION_MAPPER_CONFIG">
<column name="USER_FEDERATION_MAPPER_ID" type="VARCHAR(36)"/>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This index is unnecessary because there is already an index for primary key on USER_FEDERATION_MAPPER_CONFIG(USER_FEDERATION_MAPPER_ID, NAME) named constraint_fedmapper_cfg_pm. Please remove.

<column name="REALM_ID" type="VARCHAR(36)"/>
</createIndex>
<createIndex indexName="IDX_ID_PROV_CONF_ID_PROV" tableName="IDENTITY_PROVIDER_CONFIG">
<column name="IDENTITY_PROVIDER_ID" type="VARCHAR(36)"/>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This index is unnecessary because there is already an index for primary key on IDENTITY_PROVIDER_CONFIG(IDENTITY_PROVIDER_ID, NAME) named constraint_d. Please remove.

@glavoie
Copy link
Contributor Author

glavoie commented May 15, 2017

Thanks for the review. I'm sorry for the amount of duplicates. Looks like the query I used totally missed the duplicates through composite indices. I'll double check everything and I'll update the PR with the changes.

@glavoie
Copy link
Contributor Author

glavoie commented May 15, 2017

Updated changeset pushed!

@hmlnarik
Copy link
Contributor

@glavoie Thank you.
@stianst This version is good to go.

@stianst stianst merged commit e3a04eb into keycloak:master May 23, 2017
@stianst
Copy link
Contributor

stianst commented May 23, 2017

@glavoie Thanks for this contribution and sorry for the extraordinary long time it has taken us to merge it.

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.

4 participants