@@ -12,39 +12,56 @@ import (
1212
1313 "github.com/cockroachdb/cockroach/pkg/jobs/jobspb"
1414 "github.com/cockroachdb/cockroach/pkg/kv"
15+ "github.com/cockroachdb/cockroach/pkg/settings"
16+ "github.com/cockroachdb/cockroach/pkg/settings/cluster"
1517 "github.com/cockroachdb/cockroach/pkg/sql/isql"
1618 "github.com/cockroachdb/cockroach/pkg/sql/sem/tree"
19+ "github.com/cockroachdb/cockroach/pkg/util/metamorphic"
1720 "github.com/cockroachdb/errors"
1821)
1922
23+ var testingAvoidFullScans = metamorphic .ConstantWithTestBool (
24+ "jobs.avoid_full_scans_in_find_running_jobs" ,
25+ false , /* defaultValue */
26+ )
27+
28+ var avoidFullScans = settings .RegisterBoolSetting (
29+ settings .ApplicationLevel ,
30+ "jobs.avoid_full_scans_in_find_running_jobs.enabled" ,
31+ "when true, enables hints to avoid full scans for internal, jobs-related queries" ,
32+ testingAvoidFullScans )
33+
2034// RunningJobExists checks that whether there are any job of the given types
2135// in the pending, running, or paused state, optionally ignoring the job with
2236// the ID specified by ignoreJobID as well as any jobs created after it, if
2337// the passed ID is not InvalidJobID.
2438func RunningJobExists (
25- ctx context.Context , ignoreJobID jobspb.JobID , txn isql.Txn , jobTypes ... jobspb.Type ,
39+ ctx context.Context ,
40+ cs * cluster.Settings ,
41+ ignoreJobID jobspb.JobID ,
42+ txn isql.Txn ,
43+ jobTypes ... jobspb.Type ,
2644) (exists bool , retErr error ) {
2745 typeStrs , err := getJobTypeStrs (jobTypes )
2846 if err != nil {
2947 return false , err
3048 }
3149
32- orderBy := " ORDER BY created"
50+ orderBy := "ORDER BY created"
3351 if ignoreJobID == jobspb .InvalidJobID {
3452 // There is no need to order by the created column if there is no job to
3553 // ignore.
3654 orderBy = ""
3755 }
3856
39- stmt := `
40- SELECT
41- id
42- FROM
43- system.jobs@jobs_status_created_idx
44- WHERE
45- job_type IN ` + typeStrs + ` AND
46- status IN ` + NonTerminalStateTupleString + orderBy + `
47- LIMIT 1`
57+ hint := "jobs_status_created_idx"
58+ if avoidFullScans .Get (& cs .SV ) {
59+ hint = "{FORCE_INDEX=jobs_status_created_idx,AVOID_FULL_SCAN}"
60+ }
61+
62+ q := `SELECT id FROM system.jobs@%s WHERE job_type IN %s AND status IN %s %s LIMIT 1`
63+ stmt := fmt .Sprintf (q , hint , typeStrs , NonTerminalStateTupleString , orderBy )
64+
4865 it , err := txn .QueryIterator (
4966 ctx ,
5067 "find-running-jobs-of-type" ,
@@ -74,28 +91,31 @@ LIMIT 1`
7491// by ignoreJobID as well as any jobs created after it, if the passed ID is not
7592// InvalidJobID.
7693func RunningJobs (
77- ctx context.Context , ignoreJobID jobspb.JobID , txn isql.Txn , jobTypes ... jobspb.Type ,
94+ ctx context.Context ,
95+ cs * cluster.Settings ,
96+ ignoreJobID jobspb.JobID ,
97+ txn isql.Txn ,
98+ jobTypes ... jobspb.Type ,
7899) (jobIDs []jobspb.JobID , retErr error ) {
79100 typeStrs , err := getJobTypeStrs (jobTypes )
80101 if err != nil {
81102 return jobIDs , err
82103 }
83104
84- orderBy := " ORDER BY created"
105+ orderBy := "ORDER BY created"
85106 if ignoreJobID == jobspb .InvalidJobID {
86107 // There is no need to order by the created column if there is no job to
87108 // ignore.
88109 orderBy = ""
89110 }
90111
91- stmt := `
92- SELECT
93- id
94- FROM
95- system.jobs@jobs_status_created_idx
96- WHERE
97- job_type IN ` + typeStrs + ` AND
98- status IN ` + NonTerminalStateTupleString + orderBy
112+ hint := "jobs_status_created_idx"
113+ if avoidFullScans .Get (& cs .SV ) {
114+ hint = "{FORCE_INDEX=jobs_status_created_idx,AVOID_FULL_SCAN}"
115+ }
116+
117+ q := `SELECT id FROM system.jobs@%s WHERE job_type IN %s AND status IN %s %s`
118+ stmt := fmt .Sprintf (q , hint , typeStrs , NonTerminalStateTupleString , orderBy )
99119 it , err := txn .QueryIterator (
100120 ctx ,
101121 "find-all-running-jobs-of-type" ,
0 commit comments