Files
tidb/pkg/statistics/handle/autoanalyze/priorityqueue/interval_test.go
2024-03-01 13:36:32 +00:00

389 lines
8.5 KiB
Go

// Copyright 2024 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package priorityqueue_test
import (
"testing"
"time"
"github.com/pingcap/tidb/pkg/session"
"github.com/pingcap/tidb/pkg/sessionctx"
"github.com/pingcap/tidb/pkg/statistics/handle/autoanalyze/priorityqueue"
"github.com/pingcap/tidb/pkg/testkit"
"github.com/stretchr/testify/require"
)
func TestGetAverageAnalysisDuration(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec(session.CreateAnalyzeJobs)
// Empty table.
se := tk.Session()
sctx := se.(sessionctx.Context)
avgDuration, err := priorityqueue.GetAverageAnalysisDuration(
sctx,
"example_schema", "example_table", "example_partition",
)
require.NoError(t, err)
require.Equal(t, time.Duration(priorityqueue.NoRecord), avgDuration)
initJobs(tk)
// Partitioned table.
insertMultipleFinishedJobs(tk, "example_table", "example_partition")
// Only one partition.
avgDuration, err = priorityqueue.GetAverageAnalysisDuration(
sctx,
"example_schema", "example_table", "example_partition",
)
require.NoError(t, err)
require.Equal(t, time.Duration(3600)*time.Second, avgDuration)
// Multiple partitions.
avgDuration, err = priorityqueue.GetAverageAnalysisDuration(
sctx,
"example_schema", "example_table", "example_partition", "example_partition1",
)
require.NoError(t, err)
require.Equal(t, time.Duration(3600)*time.Second, avgDuration)
// Non-partitioned table.
insertMultipleFinishedJobs(tk, "example_table1", "")
avgDuration, err = priorityqueue.GetAverageAnalysisDuration(sctx, "example_schema", "example_table1")
require.NoError(t, err)
require.Equal(t, time.Duration(3600)*time.Second, avgDuration)
}
func insertMultipleFinishedJobs(tk *testkit.TestKit, tableName string, partitionName string) {
jobs := []struct {
dbName string
tableName string
partitionName string
startTime string
endTime string
}{
// This is a special case its duration is 30 minutes.
// But the id is smaller than the following records.
// So it will not be selected.
{"example_schema", tableName, partitionName, "2022-01-01 7:00:00", "2022-01-01 7:30:00"},
// Other records.
{"example_schema", tableName, partitionName, "2022-01-01 09:00:00", "2022-01-01 10:00:00"},
{"example_schema", tableName, partitionName, "2022-01-01 10:00:00", "2022-01-01 11:00:00"},
{"example_schema", tableName, partitionName, "2022-01-01 11:00:00", "2022-01-01 12:00:00"},
{"example_schema", tableName, partitionName, "2022-01-01 13:00:00", "2022-01-01 14:00:00"},
{"example_schema", tableName, partitionName, "2022-01-01 14:00:00", "2022-01-01 15:00:00"},
}
for _, job := range jobs {
insertFinishedJob(tk, job.dbName, job.tableName, job.partitionName, job.startTime, job.endTime)
}
}
func TestGetLastFailedAnalysisDuration(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec(session.CreateAnalyzeJobs)
// Empty table.
se := tk.Session()
sctx := se.(sessionctx.Context)
lastFailedDuration, err := priorityqueue.GetLastFailedAnalysisDuration(
sctx,
"example_schema", "example_table", "example_partition",
)
require.NoError(t, err)
require.Equal(t, time.Duration(priorityqueue.NoRecord), lastFailedDuration)
initJobs(tk)
// Partitioned table.
insertFailedJob(tk, "example_schema", "example_table", "example_partition")
insertFailedJob(tk, "example_schema", "example_table", "example_partition1")
// Only one partition.
lastFailedDuration, err = priorityqueue.GetLastFailedAnalysisDuration(
sctx,
"example_schema", "example_table", "example_partition",
)
require.NoError(t, err)
require.GreaterOrEqual(t, lastFailedDuration, time.Duration(24)*time.Hour)
// Multiple partitions.
lastFailedDuration, err = priorityqueue.GetLastFailedAnalysisDuration(
sctx,
"example_schema", "example_table", "example_partition", "example_partition1",
)
require.NoError(t, err)
require.GreaterOrEqual(t, lastFailedDuration, time.Duration(24)*time.Hour)
// Non-partitioned table.
insertFailedJob(tk, "example_schema", "example_table1", "")
lastFailedDuration, err = priorityqueue.GetLastFailedAnalysisDuration(sctx, "example_schema", "example_table1")
require.NoError(t, err)
require.GreaterOrEqual(t, lastFailedDuration, time.Duration(24)*time.Hour)
}
func initJobs(tk *testkit.TestKit) {
tk.MustExec(`
INSERT INTO mysql.analyze_jobs (
table_schema,
table_name,
partition_name,
job_info,
start_time,
state,
instance
) VALUES (
'example_schema',
'example_table',
'example_partition',
'Job information for pending job',
NULL,
'pending',
'example_instance'
);
`)
tk.MustExec(`
INSERT INTO mysql.analyze_jobs (
table_schema,
table_name,
partition_name,
job_info,
start_time,
state,
instance
) VALUES (
'example_schema',
'example_table',
'example_partition',
'Job information for running job',
'2022-01-01 10:00:00',
'running',
'example_instance'
);
`)
tk.MustExec(`
INSERT INTO mysql.analyze_jobs (
table_schema,
table_name,
partition_name,
job_info,
start_time,
end_time,
state,
fail_reason,
instance
) VALUES (
'example_schema',
'example_table',
'example_partition',
'Job information for failed job',
'2022-01-01 09:00:00',
'2022-01-01 10:00:00',
'failed',
'Some reason for failure',
'example_instance'
);
`)
}
func insertFinishedJob(
tk *testkit.TestKit,
dbName string,
tableName string,
partitionName string,
startTime string,
endTime string,
) {
if partitionName == "" {
tk.MustExec(`
INSERT INTO mysql.analyze_jobs (
table_schema,
table_name,
job_info,
start_time,
end_time,
state,
instance
) VALUES (
?,
?,
'Job information for finished job',
?,
?,
'finished',
'example_instance'
);
`,
dbName,
tableName,
startTime,
endTime,
)
} else {
tk.MustExec(`
INSERT INTO mysql.analyze_jobs (
table_schema,
table_name,
partition_name,
job_info,
start_time,
end_time,
state,
instance
) VALUES (
?,
?,
?,
'Job information for finished job',
?,
?,
'finished',
'example_instance'
);
`,
dbName,
tableName,
partitionName,
startTime,
endTime,
)
}
}
func insertFailedJob(
tk *testkit.TestKit,
dbName string,
tableName string,
partitionName string,
) {
if partitionName == "" {
tk.MustExec(`
INSERT INTO mysql.analyze_jobs (
table_schema,
table_name,
job_info,
start_time,
end_time,
state,
fail_reason,
instance
) VALUES (
?,
?,
'Job information for failed job',
'2024-01-01 09:00:00',
'2024-01-01 10:00:00',
'failed',
'Some reason for failure',
'example_instance'
);
`,
dbName,
tableName,
)
} else {
tk.MustExec(`
INSERT INTO mysql.analyze_jobs (
table_schema,
table_name,
partition_name,
job_info,
start_time,
end_time,
state,
fail_reason,
instance
) VALUES (
?,
?,
?,
'Job information for failed job',
'2024-01-01 09:00:00',
'2024-01-01 10:00:00',
'failed',
'Some reason for failure',
'example_instance'
);
`,
dbName,
tableName,
partitionName,
)
}
}
func insertFailedJobWithStartTime(
tk *testkit.TestKit,
dbName string,
tableName string,
partitionName string,
startTime string,
) {
if partitionName == "" {
tk.MustExec(`
INSERT INTO mysql.analyze_jobs (
table_schema,
table_name,
job_info,
start_time,
end_time,
state,
fail_reason,
instance
) VALUES (
?,
?,
'Job information for failed job',
?,
'2024-01-01 10:00:00',
'failed',
'Some reason for failure',
'example_instance'
);
`,
dbName,
tableName,
startTime,
)
} else {
tk.MustExec(`
INSERT INTO mysql.analyze_jobs (
table_schema,
table_name,
partition_name,
job_info,
start_time,
end_time,
state,
fail_reason,
instance
) VALUES (
?,
?,
?,
'Job information for failed job',
?,
'2024-01-01 10:00:00',
'failed',
'Some reason for failure',
'example_instance'
);
`,
dbName,
tableName,
partitionName,
startTime,
)
}
}