Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions docs/user/interfaces/endpoint.rst
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,58 @@ Result set::
"status": 200
}

Profile [Experimental]
======================

Description
-----------

Profiling captures per-stage timings (in milliseconds) for SQL query
execution. To enable profiling, set ``"profile": true`` in the request
body alongside ``"query"``.

.. note::
The ``profile`` parameter only takes effect when the query runs on
the Analytics Engine. In all other cases the flag is silently ignored.

Profile output is returned only for regular query execution (not
``_explain``) and only with the default ``format=jdbc``.

Example
-------

Request::

POST /_plugins/_sql
{
"query": "SELECT customer_id, SUM(amount) FROM orders GROUP BY customer_id",
"profile": true
}

Expected output (trimmed)::

{
"profile": {
"summary": {
"total_time_ms": 33.34
},
"phases": {
"analyze": { "time_ms": 8.68 },
"optimize": { "time_ms": 18.2 },
"execute": { "time_ms": 4.87 },
"format": { "time_ms": 0.05 }
},
"plan": {
"node": "EnumerableCalc",
"time_ms": 4.82,
"rows": 2,
"children": [
{ "node": "CalciteEnumerableIndexScan", "time_ms": 4.12, "rows": 2 }
]
}
}
}
Comment thread
dai-chen marked this conversation as resolved.

Fetch Size (PPL) [Experimental]
================================

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ public void onFailure(Exception e) {
unifiedQueryHandler.execute(
sqlRequest.getQuery(),
QueryType.SQL,
false,
sqlRequest.isProfileEnabled(),
new ActionListener<>() {
@Override
public void onResponse(TransportPPLQueryResponse response) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,9 @@
@RequiredArgsConstructor
public class SQLQueryRequest {
private static final String QUERY_FIELD_CURSOR = "cursor";
private static final String QUERY_FIELD_PROFILE = "profile";
private static final Set<String> SUPPORTED_FIELDS =
Set.of("query", "fetch_size", "parameters", QUERY_FIELD_CURSOR);
Set.of("query", "fetch_size", "parameters", QUERY_FIELD_CURSOR, QUERY_FIELD_PROFILE);
private static final String QUERY_PARAMS_FORMAT = "format";
private static final String QUERY_PARAMS_SANITIZE = "sanitize";
private static final String QUERY_PARAMS_PRETTY = "pretty";
Expand Down Expand Up @@ -118,6 +119,14 @@ public boolean isExplainRequest() {
return path.endsWith("/_explain");
}

/** Check if profiling should run for this request. */
public boolean isProfileEnabled() {
return jsonContent != null
&& jsonContent.optBoolean(QUERY_FIELD_PROFILE, false)
&& !isExplainRequest()
&& Format.JDBC.getFormatName().equalsIgnoreCase(format);
}

public boolean isCursorCloseRequest() {
return path.endsWith("/close");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,70 @@ public void should_support_raw_format() {
assertTrue(csvRequest.isSupported());
}

@Test
public void should_support_query_with_profile_field() {
SQLQueryRequest request =
SQLQueryRequestBuilder.request("SELECT 1")
.jsonContent("{\"query\": \"SELECT 1\", \"profile\": true}")
.build();
assertTrue(request.isSupported());
}

@Test
public void should_disable_profile_when_no_json_content() {
SQLQueryRequest request =
new SQLQueryRequest(null, "SELECT 1", "_plugins/_sql", Map.of(), null);
assertFalse(request.isProfileEnabled());
}

@Test
public void should_disable_profile_when_profile_field_absent() {
SQLQueryRequest request =
new SQLQueryRequest(
new JSONObject("{\"query\": \"SELECT 1\"}"),
"SELECT 1",
"_plugins/_sql",
Map.of(),
null);
assertFalse(request.isProfileEnabled());
}

@Test
public void should_enable_profile_for_jdbc_query() {
SQLQueryRequest request =
new SQLQueryRequest(
new JSONObject("{\"query\": \"SELECT 1\", \"profile\": true}"),
"SELECT 1",
"_plugins/_sql",
Map.of(),
null);
assertTrue(request.isProfileEnabled());
}

@Test
public void should_disable_profile_on_explain_path() {
SQLQueryRequest request =
new SQLQueryRequest(
new JSONObject("{\"query\": \"SELECT 1\", \"profile\": true}"),
"SELECT 1",
"_plugins/_sql/_explain",
Map.of(),
null);
assertFalse(request.isProfileEnabled());
}

@Test
public void should_disable_profile_for_non_jdbc_format() {
SQLQueryRequest request =
new SQLQueryRequest(
new JSONObject("{\"query\": \"SELECT 1\", \"profile\": true}"),
"SELECT 1",
"_plugins/_sql",
Map.of("format", "csv"),
null);
assertFalse(request.isProfileEnabled());
}

/** SQL query request build helper to improve test data setup readability. */
private static class SQLQueryRequestBuilder {
private String jsonContent;
Expand Down
Loading