diff --git a/apps/studio/components/interfaces/QueryInsights/QueryInsights.tsx b/apps/studio/components/interfaces/QueryInsights/QueryInsights.tsx
index 7996927be59..ee047a84bd8 100644
--- a/apps/studio/components/interfaces/QueryInsights/QueryInsights.tsx
+++ b/apps/studio/components/interfaces/QueryInsights/QueryInsights.tsx
@@ -11,6 +11,7 @@ import {
TooltipContent,
TooltipTrigger,
} from 'ui'
+import ShimmeringLoader from 'ui-patterns/ShimmeringLoader'
import { InformationCircleIcon } from '@heroicons/react/16/solid'
import dayjs from 'dayjs'
import { MetricsChart } from './MetricsChart/MetricsChart'
@@ -68,7 +69,7 @@ export const QueryInsights = () => {
)
// Always fetch query latency data for p95 calculation
- const { data: latencyData } = useQueryInsightsMetrics(
+ const { data: latencyData, isLoading: isLoadingLatency } = useQueryInsightsMetrics(
ref,
'query_latency',
timeRange.period_start.date,
@@ -76,7 +77,7 @@ export const QueryInsights = () => {
)
// Always fetch rows read data for total calculation
- const { data: rowsReadData } = useQueryInsightsMetrics(
+ const { data: rowsReadData, isLoading: isLoadingRowsRead } = useQueryInsightsMetrics(
ref,
'rows_read',
timeRange.period_start.date,
@@ -84,7 +85,7 @@ export const QueryInsights = () => {
)
// Always fetch issues data for issues calculation
- const { data: issuesData } = useQueryInsightsMetrics(
+ const { data: issuesData, isLoading: isLoadingIssues } = useQueryInsightsMetrics(
ref,
'issues',
timeRange.period_start.date,
@@ -92,7 +93,7 @@ export const QueryInsights = () => {
)
// Always fetch cache hits data for hit ratio calculation
- const { data: cacheHitsData } = useQueryInsightsMetrics(
+ const { data: cacheHitsData, isLoading: isLoadingCacheHits } = useQueryInsightsMetrics(
ref,
'cache_hits',
timeRange.period_start.date,
@@ -100,7 +101,7 @@ export const QueryInsights = () => {
)
// Always fetch calls data for total calculation
- const { data: callsData } = useQueryInsightsMetrics(
+ const { data: callsData, isLoading: isLoadingCalls } = useQueryInsightsMetrics(
ref,
'calls',
timeRange.period_start.date,
@@ -122,6 +123,7 @@ export const QueryInsights = () => {
// Calculate p95 latency for the query latency tab
const p95Latency = useMemo(() => {
+ if (isLoadingLatency) return null
if (latencyData && latencyData.length > 0) {
// Calculate average p95 across all data points in the current timeframe
const validP95Values = latencyData
@@ -134,11 +136,12 @@ export const QueryInsights = () => {
return `${averageP95.toFixed(2)}ms`
}
}
- return null
- }, [latencyData])
+ return '0ms'
+ }, [latencyData, isLoadingLatency])
// Calculate total rows read for the rows read tab
const totalRowsRead = useMemo(() => {
+ if (isLoadingRowsRead) return null
if (rowsReadData && rowsReadData.length > 0) {
const total = rowsReadData.reduce((sum, point) => {
const value = Number(point.value) || 0
@@ -147,19 +150,21 @@ export const QueryInsights = () => {
return total.toLocaleString()
}
return '0'
- }, [rowsReadData])
+ }, [rowsReadData, isLoadingRowsRead])
// Calculate error count for the errors tab
const errorCount = useMemo(() => {
+ if (isLoadingIssues) return null
if (issuesData && issuesData.length > 0) {
const totalIssues = issuesData.reduce((sum, point) => sum + (point.value || 0), 0)
return `${totalIssues} slow queries`
}
return '0 slow queries'
- }, [issuesData])
+ }, [issuesData, isLoadingIssues])
// Calculate total calls for the calls tab
const totalCalls = useMemo(() => {
+ if (isLoadingCalls) return null
if (callsData && callsData.length > 0) {
const total = callsData.reduce((sum, point) => {
const value = Number(point.value) || 0
@@ -168,10 +173,11 @@ export const QueryInsights = () => {
return total.toLocaleString()
}
return '0'
- }, [callsData])
+ }, [callsData, isLoadingCalls])
// Calculate cache hit ratio for the cache hits tab
const cacheHitRatio = useMemo(() => {
+ if (isLoadingCacheHits) return null
if (cacheHitsData && cacheHitsData.length > 0) {
// Calculate cache hit ratio using the same logic as the chart
const lastPoint = cacheHitsData[cacheHitsData.length - 1]
@@ -185,7 +191,7 @@ export const QueryInsights = () => {
}
}
return '0%'
- }, [cacheHitsData])
+ }, [cacheHitsData, isLoadingCacheHits])
// Debug logging
console.log('🔍 [QueryInsights] Debug info:', {
@@ -201,39 +207,43 @@ export const QueryInsights = () => {
})
// Define metrics with dynamic descriptions
- const METRICS: { id: MetricType; label: string; description: string; tooltip: string }[] = [
+ const METRICS = useMemo((): { id: MetricType; label: string; description: string | null; tooltip: string; isLoading: boolean }[] => [
{
id: 'query_latency',
label: 'Query latency',
description: `p95: ${p95Latency}`,
tooltip: 'Shows the latency of each query execution.',
+ isLoading: isLoadingLatency,
},
{
id: 'rows_read',
label: 'Rows read',
description: `${totalRowsRead}`,
tooltip: 'Displays the total number of rows read by queries over time',
+ isLoading: isLoadingRowsRead,
},
-
{
id: 'calls',
label: 'Calls',
description: `${totalCalls}`,
tooltip: 'Shows the frequency of query executions and their distribution over time',
+ isLoading: isLoadingCalls,
},
{
id: 'cache_hits',
label: 'Cache hits',
description: cacheHitRatio,
tooltip: 'Displays cache hit rates and shared buffer cache performance statistics',
+ isLoading: isLoadingCacheHits,
},
{
id: 'issues',
label: 'Issues',
description: errorCount,
tooltip: 'Shows queries with potential performance issues (slow queries)',
+ isLoading: isLoadingIssues,
},
- ]
+ ], [p95Latency, totalRowsRead, totalCalls, cacheHitRatio, errorCount, isLoadingLatency, isLoadingRowsRead, isLoadingCalls, isLoadingCacheHits, isLoadingIssues])
// Event listener for clearing the selected query
useEffect(() => {
@@ -415,9 +425,17 @@ export const QueryInsights = () => {
-
- {metric.description}
-
+ {metric.isLoading || metric.description === null ? (
+
+ ) : metric.description === '0' || metric.description === '0%' || metric.description === '0 slow queries' ? (
+
+ No data yet
+
+ ) : (
+
+ {metric.description}
+
+ )}
))}