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

Improve Performance of Contracts REST API Endpoints with High Entity Counts #10069

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
DROP INDEX IF EXISTS entity__id_type;
Copy link
Collaborator

@xin-hedera xin-hedera Jan 13, 2025

Choose a reason for hiding this comment

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

the version should be V1.103.0 and for v2 schema, need to add the same migration with version V2.8.0

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated.


CREATE INDEX entity_type_id ON entities(type, id);
HarshSawarkar marked this conversation as resolved.
Show resolved Hide resolved
22 changes: 15 additions & 7 deletions hedera-mirror-rest/controllers/contractController.js
Original file line number Diff line number Diff line change
Expand Up @@ -234,13 +234,21 @@ const getContractByIdOrAddressContractEntityQuery = ({timestampConditions, times
*/
const getContractsQuery = (whereQuery, limitQuery, order) => {
return [
`select ${contractSelectFields}`,
Copy link
Collaborator

Choose a reason for hiding this comment

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

why is this changed to a more complicated, two CTEs + one main query SQL query? If it's not driven by perf analysis, please revert.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I used the CTE to first fetch the relevant contract IDs, which reduces the number of data rows the left join needs to process. However, since I haven't conducted a performance analysis to validate the change, I will revert it for now.

`from ${Entity.tableName} ${Entity.tableAlias}`,
`left join ${Contract.tableName} ${Contract.tableAlias}`,
`on ${Entity.getFullName(Entity.ID)} = ${Contract.getFullName(Contract.ID)}`,
whereQuery,
`order by ${Entity.getFullName(Entity.ID)} ${order}`,
limitQuery,
`WITH matching_contracts AS (`,
` SELECT ${Entity.getFullName(Entity.ID)}`,
` FROM ${Entity.tableName} ${Entity.tableAlias}`,
` ${whereQuery}`,
` ORDER BY ${Entity.getFullName(Entity.ID)} ${order}`,
` ${limitQuery}`,
`),`,
`contract_details AS (`,
` SELECT ${contractSelectFields}`,
` FROM matching_contracts mc`,
` JOIN ${Entity.tableName} ${Entity.tableAlias} ON ${Entity.getFullName(Entity.ID)} = mc.${Entity.ID}`,
` LEFT JOIN ${Contract.tableName} ${Contract.tableAlias}`,
` ON ${Entity.getFullName(Entity.ID)} = ${Contract.getFullName(Contract.ID)}`,
`)`,
`SELECT * FROM contract_details`,
]
.filter((q) => q !== '')
.join('\n');
Expand Down