-
Notifications
You must be signed in to change notification settings - Fork 27
DA-1203 Modified Add Slow Running Queries tools #74
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -81,7 +81,6 @@ def run_sql_plus_plus_query( | |||||||||||||||||
| raise | ||||||||||||||||||
|
|
||||||||||||||||||
|
|
||||||||||||||||||
| # Don't expose this function to the MCP server until we have a use case | ||||||||||||||||||
| def run_cluster_query(ctx: Context, query: str, **kwargs: Any) -> list[dict[str, Any]]: | ||||||||||||||||||
| """Run a query on the cluster object and return the results as a list of JSON objects.""" | ||||||||||||||||||
|
|
||||||||||||||||||
|
|
@@ -96,3 +95,185 @@ def run_cluster_query(ctx: Context, query: str, **kwargs: Any) -> list[dict[str, | |||||||||||||||||
| except Exception as e: | ||||||||||||||||||
| logger.error(f"Error running query: {e}") | ||||||||||||||||||
| raise | ||||||||||||||||||
|
|
||||||||||||||||||
|
|
||||||||||||||||||
| def get_top_longest_running_queries( | ||||||||||||||||||
| ctx: Context, limit: int = 10 | ||||||||||||||||||
| ) -> list[dict[str, Any]]: | ||||||||||||||||||
| """Get the top N longest running queries from the system:completed_requests catalog. | ||||||||||||||||||
|
|
||||||||||||||||||
| Args: | ||||||||||||||||||
| limit: Number of queries to return (default: 10) | ||||||||||||||||||
|
|
||||||||||||||||||
| Returns: | ||||||||||||||||||
| List of queries with their average service time and count | ||||||||||||||||||
| """ | ||||||||||||||||||
| query = """ | ||||||||||||||||||
| SELECT statement, | ||||||||||||||||||
| DURATION_TO_STR(avgServiceTime) AS avgServiceTime, | ||||||||||||||||||
| COUNT(1) AS queries | ||||||||||||||||||
| FROM system:completed_requests | ||||||||||||||||||
| WHERE UPPER(statement) NOT LIKE 'INFER %' | ||||||||||||||||||
| AND UPPER(statement) NOT LIKE 'CREATE INDEX%' | ||||||||||||||||||
| AND UPPER(statement) NOT LIKE '% SYSTEM:%' | ||||||||||||||||||
| GROUP BY statement | ||||||||||||||||||
| LETTING avgServiceTime = AVG(STR_TO_DURATION(serviceTime)) | ||||||||||||||||||
| ORDER BY avgServiceTime DESC | ||||||||||||||||||
| LIMIT $limit | ||||||||||||||||||
| """ | ||||||||||||||||||
|
|
||||||||||||||||||
| return run_cluster_query(ctx, query, limit=limit) | ||||||||||||||||||
|
|
||||||||||||||||||
|
|
||||||||||||||||||
| def get_top_most_frequent_queries( | ||||||||||||||||||
| ctx: Context, limit: int = 10 | ||||||||||||||||||
| ) -> list[dict[str, Any]]: | ||||||||||||||||||
| """Get the top N most frequent queries from the system:completed_requests catalog. | ||||||||||||||||||
|
|
||||||||||||||||||
| Args: | ||||||||||||||||||
| limit: Number of queries to return (default: 10) | ||||||||||||||||||
|
|
||||||||||||||||||
| Returns: | ||||||||||||||||||
| List of queries with their frequency count | ||||||||||||||||||
| """ | ||||||||||||||||||
| query = """ | ||||||||||||||||||
| SELECT statement, | ||||||||||||||||||
| COUNT(1) AS queries | ||||||||||||||||||
| FROM system:completed_requests | ||||||||||||||||||
| WHERE UPPER(statement) NOT LIKE 'INFER %' | ||||||||||||||||||
| AND UPPER(statement) NOT LIKE 'CREATE INDEX%' | ||||||||||||||||||
| AND UPPER(statement) NOT LIKE '% SYSTEM:%' | ||||||||||||||||||
| GROUP BY statement | ||||||||||||||||||
| LETTING queries = COUNT(1) | ||||||||||||||||||
| ORDER BY queries DESC | ||||||||||||||||||
| LIMIT $limit | ||||||||||||||||||
| """ | ||||||||||||||||||
|
|
||||||||||||||||||
| return run_cluster_query(ctx, query, limit=limit) | ||||||||||||||||||
|
|
||||||||||||||||||
|
|
||||||||||||||||||
| def get_queries_with_largest_response_sizes( | ||||||||||||||||||
| ctx: Context, limit: int = 10 | ||||||||||||||||||
| ) -> list[dict[str, Any]]: | ||||||||||||||||||
| """Get queries with the largest response sizes from the system:completed_requests catalog. | ||||||||||||||||||
|
|
||||||||||||||||||
| Args: | ||||||||||||||||||
| limit: Number of queries to return (default: 10) | ||||||||||||||||||
|
|
||||||||||||||||||
| Returns: | ||||||||||||||||||
| List of queries with their average result size in bytes, KB, and MB | ||||||||||||||||||
| """ | ||||||||||||||||||
| query = """ | ||||||||||||||||||
| SELECT statement, | ||||||||||||||||||
| avgResultSize AS avgResultSizeBytes, | ||||||||||||||||||
| (avgResultSize / 1000) AS avgResultSizeKB, | ||||||||||||||||||
| (avgResultSize / 1000000) AS avgResultSizeMB, | ||||||||||||||||||
| COUNT(1) AS queries | ||||||||||||||||||
| FROM system:completed_requests | ||||||||||||||||||
| WHERE UPPER(statement) NOT LIKE 'INFER %' | ||||||||||||||||||
| AND UPPER(statement) NOT LIKE 'CREATE INDEX%' | ||||||||||||||||||
| AND UPPER(statement) NOT LIKE '% SYSTEM:%' | ||||||||||||||||||
| GROUP BY statement | ||||||||||||||||||
| LETTING avgResultSize = AVG(resultSize) | ||||||||||||||||||
| ORDER BY avgResultSize DESC | ||||||||||||||||||
| LIMIT $limit | ||||||||||||||||||
| """ | ||||||||||||||||||
|
|
||||||||||||||||||
| return run_cluster_query(ctx, query, limit=limit) | ||||||||||||||||||
|
|
||||||||||||||||||
|
|
||||||||||||||||||
| def get_queries_with_large_result_count( | ||||||||||||||||||
| ctx: Context, limit: int = 10 | ||||||||||||||||||
| ) -> list[dict[str, Any]]: | ||||||||||||||||||
| """Get queries with the largest result counts from the system:completed_requests catalog. | ||||||||||||||||||
|
|
||||||||||||||||||
| Args: | ||||||||||||||||||
| limit: Number of queries to return (default: 10) | ||||||||||||||||||
|
|
||||||||||||||||||
| Returns: | ||||||||||||||||||
| List of queries with their average result count | ||||||||||||||||||
| """ | ||||||||||||||||||
| query = """ | ||||||||||||||||||
| SELECT statement, | ||||||||||||||||||
| avgResultCount, | ||||||||||||||||||
| COUNT(1) AS queries | ||||||||||||||||||
| FROM system:completed_requests | ||||||||||||||||||
| WHERE UPPER(statement) NOT LIKE 'INFER %' | ||||||||||||||||||
| AND UPPER(statement) NOT LIKE 'CREATE INDEX%' | ||||||||||||||||||
| AND UPPER(statement) NOT LIKE '% SYSTEM:%' | ||||||||||||||||||
| GROUP BY statement | ||||||||||||||||||
| LETTING avgResultCount = AVG(resultCount) | ||||||||||||||||||
| ORDER BY avgResultCount DESC | ||||||||||||||||||
| LIMIT $limit | ||||||||||||||||||
| """ | ||||||||||||||||||
|
|
||||||||||||||||||
| return run_cluster_query(ctx, query, limit=limit) | ||||||||||||||||||
|
|
||||||||||||||||||
|
|
||||||||||||||||||
| def get_queries_using_primary_index( | ||||||||||||||||||
| ctx: Context, limit: int = 10 | ||||||||||||||||||
| ) -> list[dict[str, Any]]: | ||||||||||||||||||
| """Get queries that use a primary index from the system:completed_requests catalog. | ||||||||||||||||||
|
|
||||||||||||||||||
| Args: | ||||||||||||||||||
| limit: Number of queries to return (default: 10) | ||||||||||||||||||
|
|
||||||||||||||||||
| Returns: | ||||||||||||||||||
| List of queries that use primary indexes, ordered by result count | ||||||||||||||||||
| """ | ||||||||||||||||||
| query = """ | ||||||||||||||||||
| SELECT * | ||||||||||||||||||
| FROM system:completed_requests | ||||||||||||||||||
| WHERE phaseCounts.`primaryScan` IS NOT MISSING | ||||||||||||||||||
| AND UPPER(statement) NOT LIKE '% SYSTEM:%' | ||||||||||||||||||
| ORDER BY resultCount DESC | ||||||||||||||||||
| LIMIT $limit | ||||||||||||||||||
| """ | ||||||||||||||||||
|
|
||||||||||||||||||
| return run_cluster_query(ctx, query, limit=limit) | ||||||||||||||||||
|
|
||||||||||||||||||
|
|
||||||||||||||||||
| def get_queries_not_using_covering_index( | ||||||||||||||||||
| ctx: Context, limit: int = 10 | ||||||||||||||||||
| ) -> list[dict[str, Any]]: | ||||||||||||||||||
| """Get queries that don't use a covering index from the system:completed_requests catalog. | ||||||||||||||||||
|
|
||||||||||||||||||
| Args: | ||||||||||||||||||
| limit: Number of queries to return (default: 10) | ||||||||||||||||||
|
|
||||||||||||||||||
| Returns: | ||||||||||||||||||
| List of queries that perform index scans but also require fetches (not covering) | ||||||||||||||||||
| """ | ||||||||||||||||||
| query = """ | ||||||||||||||||||
| SELECT * | ||||||||||||||||||
| FROM system:completed_requests | ||||||||||||||||||
| WHERE phaseCounts.`indexScan` IS NOT MISSING | ||||||||||||||||||
| AND phaseCounts.`fetch` IS NOT MISSING | ||||||||||||||||||
| AND UPPER(statement) NOT LIKE '% SYSTEM:%' | ||||||||||||||||||
|
Comment on lines
+250
to
+252
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This query is missing filters for
Suggested change
|
||||||||||||||||||
| ORDER BY resultCount DESC | ||||||||||||||||||
| LIMIT $limit | ||||||||||||||||||
| """ | ||||||||||||||||||
|
|
||||||||||||||||||
| return run_cluster_query(ctx, query, limit=limit) | ||||||||||||||||||
|
|
||||||||||||||||||
|
|
||||||||||||||||||
| def get_queries_not_selective(ctx: Context, limit: int = 10) -> list[dict[str, Any]]: | ||||||||||||||||||
| """Get queries that are not very selective from the system:completed_requests catalog. | ||||||||||||||||||
|
|
||||||||||||||||||
| Args: | ||||||||||||||||||
| limit: Number of queries to return (default: 10) | ||||||||||||||||||
|
|
||||||||||||||||||
| Returns: | ||||||||||||||||||
| List of queries where index scans return significantly more documents than the final result | ||||||||||||||||||
| """ | ||||||||||||||||||
| query = """ | ||||||||||||||||||
| SELECT statement, | ||||||||||||||||||
| AVG(phaseCounts.`indexScan` - resultCount) AS diff | ||||||||||||||||||
|
||||||||||||||||||
| AVG(phaseCounts.`indexScan` - resultCount) AS diff | |
| AVG(GREATEST(phaseCounts.`indexScan` - resultCount, 0)) AS diff |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This query is missing filters to exclude system-level statements (like INFER, CREATE INDEX, and queries on SYSTEM: keyspaces). Including these filters, as done in other functions in this file, will help to focus on application performance issues.
| WHERE phaseCounts.`indexScan` > resultCount | |
| WHERE phaseCounts.`indexScan` > resultCount | |
| AND UPPER(statement) NOT LIKE 'INFER %' | |
| AND UPPER(statement) NOT LIKE 'CREATE INDEX%' | |
| AND UPPER(statement) NOT LIKE '% SYSTEM:%' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For consistency with other query-analyzing tools in this file, consider filtering out
INFERandCREATE INDEXstatements. This will help focus the results on application-level queries.