Repository navigation
Expand file tree
/
Copy pathAdvanced_001_QueryIdUsage.cs
More file actions
164 lines (141 loc) · 6.4 KB
/
Copy pathAdvanced_001_QueryIdUsage.cs
File metadata and controls
164 lines (141 loc) · 6.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
using ClickHouse.Driver.ADO;
using ClickHouse.Driver.ADO.Parameters;
using ClickHouse.Driver.Utility;
namespace ClickHouse.Driver.Examples;
/// <summary>
/// Demonstrates how to use Query IDs to track and monitor query execution.
/// Query IDs are useful for:
/// - Debugging and troubleshooting specific queries
/// - Tracking query execution in system.query_log
/// - Correlating client-side operations with server-side logs
/// - Monitoring query progress and performance
/// </summary>
public static class QueryIdUsage
{
public static async Task Run()
{
using var client = ExampleConfig.CreateHttpClient();
Console.WriteLine("Query ID Usage Examples\n");
// Example 1: Automatic Query ID
Console.WriteLine("1. Automatic Query ID assignment:");
await Example1_AutomaticQueryId(client);
// Example 2: Custom Query ID
Console.WriteLine("\n2. Setting a custom Query ID:");
await Example2_CustomQueryId(client);
// Example 3: Tracking query execution
Console.WriteLine("\n3. Tracking query execution in system.query_log:");
await Example3_TrackingQueryExecution(client);
// Example 4: Cancelling a query by Query ID
Console.WriteLine("\n4. Query cancellation using Query ID:");
await Example4_QueryCancellation(client);
Console.WriteLine("\nAll Query ID examples completed!");
}
private static async Task Example1_AutomaticQueryId(ClickHouseClient client)
{
// When you don't set a QueryId, the client automatically generates a GUID
var result = await client.ExecuteScalarAsync("SELECT 'Hello from ClickHouse' AS message");
Console.WriteLine($" Result: {result}");
Console.WriteLine(" (QueryId was auto-generated for this query)");
}
private static async Task Example2_CustomQueryId(ClickHouseClient client)
{
// You can set your own Query ID before executing a query
// This is useful for correlation with your application logs
var customQueryId = $"example-{Guid.NewGuid()}";
var options = new QueryOptions { QueryId = customQueryId };
Console.WriteLine($" Custom QueryId: {customQueryId}");
var version = await client.ExecuteScalarAsync("SELECT version()", options: options);
Console.WriteLine($" ClickHouse version: {version}");
}
private static async Task Example3_TrackingQueryExecution(ClickHouseClient client)
{
// Execute a query with a custom Query ID
var trackableQueryId = $"trackable-{Guid.NewGuid()}";
var options = new QueryOptions { QueryId = trackableQueryId };
await client.ExecuteNonQueryAsync("SELECT 1", options: options);
Console.WriteLine($" Executed query with ID: {trackableQueryId}");
// Wait a moment for the query to be logged
await Task.Delay(2000);
// Query system.query_log to get information about our query
var parameters = new ClickHouseParameterCollection();
parameters.AddParameter("queryId", trackableQueryId);
try
{
using var reader = await client.ExecuteReaderAsync(@"
SELECT
query_id,
type,
query_duration_ms,
read_rows,
written_rows,
memory_usage
FROM system.query_log
WHERE query_id = {queryId:String}
AND type = 'QueryFinish'
ORDER BY event_time DESC
LIMIT 1
", parameters);
if (reader.Read())
{
Console.WriteLine(" Query execution details from system.query_log:");
Console.WriteLine($" Query ID: {reader.GetString(0)}");
Console.WriteLine($" Type: {reader.GetString(1)}");
Console.WriteLine($" Duration: {reader.GetFieldValue<ulong>(2)} ms");
Console.WriteLine($" Rows read: {reader.GetFieldValue<ulong>(3)}");
Console.WriteLine($" Rows written: {reader.GetFieldValue<ulong>(4)}");
Console.WriteLine($" Memory usage: {reader.GetFieldValue<ulong>(5)} bytes");
}
else
{
Console.WriteLine(" (Query not yet in system.query_log - this table may have a delay or be disabled)");
}
}
catch (ClickHouseServerException ex) when (ex.ErrorCode == 60)
{
Console.WriteLine(" (system.query_log table not available on this server)");
}
}
private static async Task Example4_QueryCancellation(ClickHouseClient client)
{
// Demonstrate cancelling a long-running query using Query ID
var cancellableQueryId = $"cancellable-{Guid.NewGuid()}";
var options = new QueryOptions { QueryId = cancellableQueryId };
Console.WriteLine($" Query ID: {cancellableQueryId}");
Console.WriteLine(" Starting a long-running query (SELECT sleep(3))...");
// Start the long-running query in a background task
var queryTask = Task.Run(async () =>
{
try
{
await client.ExecuteScalarAsync("SELECT sleep(3)", options: options);
Console.WriteLine(" Query completed (should have been cancelled)");
}
catch (ClickHouseServerException ex)
{
// Query was killed on the server
Console.WriteLine($" Server error: {ex.Message}");
}
catch (Exception ex)
{
Console.WriteLine($" Query failed: {ex.Message}");
}
}, CancellationToken.None);
// Wait a bit for the query to start
await Task.Delay(1000);
// Cancel using KILL QUERY
Console.WriteLine($" Cancelling query using KILL QUERY...");
try
{
var killParams = new ClickHouseParameterCollection();
killParams.AddParameter("queryId", cancellableQueryId);
await client.ExecuteNonQueryAsync("KILL QUERY WHERE query_id = {queryId:String}", killParams);
Console.WriteLine(" KILL QUERY command sent");
}
catch (Exception ex)
{
Console.WriteLine($" Note: KILL QUERY failed (may require permissions): {ex.Message}");
}
// Wait for the query task to complete
await queryTask;
}
}