diff --git a/docs/generated/settings/settings-for-tenants.txt b/docs/generated/settings/settings-for-tenants.txt
index 7c505a40b16e..2f73db38e2b6 100644
--- a/docs/generated/settings/settings-for-tenants.txt
+++ b/docs/generated/settings/settings-for-tenants.txt
@@ -190,7 +190,7 @@ This session variable default should now be configured using ALTER ROLE... SET:
sql.defaults.default_int_size integer 8 "the size, in bytes, of an INT type
This cluster setting is being kept to preserve backwards-compatibility.
This session variable default should now be configured using ALTER ROLE... SET: https://www.cockroachlabs.com/docs/stable/alter-role.html" application
-sql.defaults.disallow_full_table_scans.enabled boolean false "setting to true rejects queries that have planned a full table scan
+sql.defaults.disallow_full_table_scans.enabled boolean false "setting to true rejects queries that have planned a full table scan; set large_full_scan_rows > 0 to allow small full table scans estimated to read fewer than large_full_scan_rows
This cluster setting is being kept to preserve backwards-compatibility.
This session variable default should now be configured using ALTER ROLE... SET: https://www.cockroachlabs.com/docs/stable/alter-role.html" application
sql.defaults.distsql enumeration auto "default distributed SQL execution mode [off = 0, auto = 1, on = 2, always = 3]
@@ -229,7 +229,7 @@ This session variable default should now be configured using ALTER ROLE... SET:
sql.defaults.intervalstyle enumeration postgres "default value for IntervalStyle session setting [postgres = 0, iso_8601 = 1, sql_standard = 2]
This cluster setting is being kept to preserve backwards-compatibility.
This session variable default should now be configured using ALTER ROLE... SET: https://www.cockroachlabs.com/docs/stable/alter-role.html" application
-sql.defaults.large_full_scan_rows float 1000 "default value for large_full_scan_rows session setting which determines the maximum table size allowed for a full scan when disallow_full_table_scans is set to true
+sql.defaults.large_full_scan_rows float 0 "default value for large_full_scan_rows session variable which determines the table size at which full scans are considered large and disallowed when disallow_full_table_scans is set to true; set to 0 to reject all full table or full index scans when disallow_full_table_scans is true
This cluster setting is being kept to preserve backwards-compatibility.
This session variable default should now be configured using ALTER ROLE... SET: https://www.cockroachlabs.com/docs/stable/alter-role.html" application
sql.defaults.locality_optimized_partitioned_index_scan.enabled boolean true "default value for locality_optimized_partitioned_index_scan session setting; enables searching for rows in the current region before searching remote regions
diff --git a/docs/generated/settings/settings.html b/docs/generated/settings/settings.html
index 978687cc54e2..326200f4b4a7 100644
--- a/docs/generated/settings/settings.html
+++ b/docs/generated/settings/settings.html
@@ -217,7 +217,7 @@
sql.defaults.datestyle
| enumeration | iso, mdy | default value for DateStyle session setting [iso, mdy = 0, iso, dmy = 1, iso, ymd = 2] This cluster setting is being kept to preserve backwards-compatibility. This session variable default should now be configured using ALTER ROLE... SET | Serverless/Dedicated/Self-Hosted |
sql.defaults.default_hash_sharded_index_bucket_count
| integer | 16 | used as bucket count if bucket count is not specified in hash sharded index definition This cluster setting is being kept to preserve backwards-compatibility. This session variable default should now be configured using ALTER ROLE... SET | Serverless/Dedicated/Self-Hosted |
sql.defaults.default_int_size
| integer | 8 | the size, in bytes, of an INT type This cluster setting is being kept to preserve backwards-compatibility. This session variable default should now be configured using ALTER ROLE... SET | Serverless/Dedicated/Self-Hosted |
-sql.defaults.disallow_full_table_scans.enabled
| boolean | false | setting to true rejects queries that have planned a full table scan This cluster setting is being kept to preserve backwards-compatibility. This session variable default should now be configured using ALTER ROLE... SET | Serverless/Dedicated/Self-Hosted |
+sql.defaults.disallow_full_table_scans.enabled
| boolean | false | setting to true rejects queries that have planned a full table scan; set large_full_scan_rows > 0 to allow small full table scans estimated to read fewer than large_full_scan_rows This cluster setting is being kept to preserve backwards-compatibility. This session variable default should now be configured using ALTER ROLE... SET | Serverless/Dedicated/Self-Hosted |
sql.defaults.distsql
| enumeration | auto | default distributed SQL execution mode [off = 0, auto = 1, on = 2, always = 3] This cluster setting is being kept to preserve backwards-compatibility. This session variable default should now be configured using ALTER ROLE... SET | Serverless/Dedicated/Self-Hosted |
sql.defaults.experimental_alter_column_type.enabled
| boolean | false | default value for experimental_alter_column_type session setting; enables the use of ALTER COLUMN TYPE for general conversions This cluster setting is being kept to preserve backwards-compatibility. This session variable default should now be configured using ALTER ROLE... SET | Serverless/Dedicated/Self-Hosted |
sql.defaults.experimental_distsql_planning
| enumeration | off | default experimental_distsql_planning mode; enables experimental opt-driven DistSQL planning [off = 0, on = 1] This cluster setting is being kept to preserve backwards-compatibility. This session variable default should now be configured using ALTER ROLE... SET | Serverless/Dedicated/Self-Hosted |
@@ -230,7 +230,7 @@
sql.defaults.implicit_select_for_update.enabled
| boolean | true | default value for enable_implicit_select_for_update session setting; enables FOR UPDATE locking during the row-fetch phase of mutation statements This cluster setting is being kept to preserve backwards-compatibility. This session variable default should now be configured using ALTER ROLE... SET | Serverless/Dedicated/Self-Hosted |
sql.defaults.insert_fast_path.enabled
| boolean | true | default value for enable_insert_fast_path session setting; enables a specialized insert path This cluster setting is being kept to preserve backwards-compatibility. This session variable default should now be configured using ALTER ROLE... SET | Serverless/Dedicated/Self-Hosted |
sql.defaults.intervalstyle
| enumeration | postgres | default value for IntervalStyle session setting [postgres = 0, iso_8601 = 1, sql_standard = 2] This cluster setting is being kept to preserve backwards-compatibility. This session variable default should now be configured using ALTER ROLE... SET | Serverless/Dedicated/Self-Hosted |
-sql.defaults.large_full_scan_rows
| float | 1000 | default value for large_full_scan_rows session setting which determines the maximum table size allowed for a full scan when disallow_full_table_scans is set to true This cluster setting is being kept to preserve backwards-compatibility. This session variable default should now be configured using ALTER ROLE... SET | Serverless/Dedicated/Self-Hosted |
+sql.defaults.large_full_scan_rows
| float | 0 | default value for large_full_scan_rows session variable which determines the table size at which full scans are considered large and disallowed when disallow_full_table_scans is set to true; set to 0 to reject all full table or full index scans when disallow_full_table_scans is true This cluster setting is being kept to preserve backwards-compatibility. This session variable default should now be configured using ALTER ROLE... SET | Serverless/Dedicated/Self-Hosted |
sql.defaults.locality_optimized_partitioned_index_scan.enabled
| boolean | true | default value for locality_optimized_partitioned_index_scan session setting; enables searching for rows in the current region before searching remote regions This cluster setting is being kept to preserve backwards-compatibility. This session variable default should now be configured using ALTER ROLE... SET | Serverless/Dedicated/Self-Hosted |
sql.defaults.lock_timeout
| duration | 0s | default value for the lock_timeout; default value for the lock_timeout session setting; controls the duration a query is permitted to wait while attempting to acquire a lock on a key or while blocking on an existing lock in order to perform a non-locking read on a key; if set to 0, there is no timeout This cluster setting is being kept to preserve backwards-compatibility. This session variable default should now be configured using ALTER ROLE... SET | Serverless/Dedicated/Self-Hosted |
sql.defaults.on_update_rehome_row.enabled
| boolean | true | default value for on_update_rehome_row; enables ON UPDATE rehome_row() expressions to trigger on updates This cluster setting is being kept to preserve backwards-compatibility. This session variable default should now be configured using ALTER ROLE... SET | Serverless/Dedicated/Self-Hosted |
diff --git a/pkg/sql/exec_util.go b/pkg/sql/exec_util.go
index 4e7dc998d8c7..607dbbb15d82 100644
--- a/pkg/sql/exec_util.go
+++ b/pkg/sql/exec_util.go
@@ -633,7 +633,9 @@ var SerialNormalizationMode = settings.RegisterEnumSetting(
var disallowFullTableScans = settings.RegisterBoolSetting(
settings.ApplicationLevel,
`sql.defaults.disallow_full_table_scans.enabled`,
- "setting to true rejects queries that have planned a full table scan",
+ "setting to true rejects queries that have planned a full table scan; set "+
+ "large_full_scan_rows > 0 to allow small full table scans estimated to "+
+ "read fewer than large_full_scan_rows",
false,
settings.WithPublic)
@@ -709,10 +711,11 @@ var txnRowsReadErr = settings.RegisterIntSetting(
var largeFullScanRows = settings.RegisterFloatSetting(
settings.ApplicationLevel,
"sql.defaults.large_full_scan_rows",
- "default value for large_full_scan_rows session setting which determines "+
- "the maximum table size allowed for a full scan when disallow_full_table_scans "+
- "is set to true",
- 1000.0,
+ "default value for large_full_scan_rows session variable which determines "+
+ "the table size at which full scans are considered large and disallowed "+
+ "when disallow_full_table_scans is set to true; set to 0 to reject all "+
+ "full table or full index scans when disallow_full_table_scans is true",
+ 0,
settings.WithPublic)
var costScansWithDefaultColSize = settings.RegisterBoolSetting(
diff --git a/pkg/sql/logictest/testdata/logic_test/information_schema b/pkg/sql/logictest/testdata/logic_test/information_schema
index 3a14b1ad6827..226eca6db79c 100644
--- a/pkg/sql/logictest/testdata/logic_test/information_schema
+++ b/pkg/sql/logictest/testdata/logic_test/information_schema
@@ -6273,7 +6273,7 @@ is_superuser on
join_reader_index_join_strategy_batch_size 4.0 MiB
join_reader_no_ordering_strategy_batch_size 2.0 MiB
join_reader_ordering_strategy_batch_size 100 KiB
-large_full_scan_rows 1000
+large_full_scan_rows 0
lc_collate C.UTF-8
lc_ctype C.UTF-8
lc_messages C.UTF-8
diff --git a/pkg/sql/logictest/testdata/logic_test/pg_catalog b/pkg/sql/logictest/testdata/logic_test/pg_catalog
index 07bd7fbee1bd..1a53607809ea 100644
--- a/pkg/sql/logictest/testdata/logic_test/pg_catalog
+++ b/pkg/sql/logictest/testdata/logic_test/pg_catalog
@@ -2918,7 +2918,7 @@ is_superuser on N
join_reader_index_join_strategy_batch_size 4.0 MiB NULL NULL NULL string
join_reader_no_ordering_strategy_batch_size 2.0 MiB NULL NULL NULL string
join_reader_ordering_strategy_batch_size 100 KiB NULL NULL NULL string
-large_full_scan_rows 1000 NULL NULL NULL string
+large_full_scan_rows 0 NULL NULL NULL string
lc_collate C.UTF-8 NULL NULL NULL string
lc_ctype C.UTF-8 NULL NULL NULL string
lc_messages C.UTF-8 NULL NULL NULL string
@@ -3110,7 +3110,7 @@ is_superuser on N
join_reader_index_join_strategy_batch_size 4.0 MiB NULL user NULL 4.0 MiB 4.0 MiB
join_reader_no_ordering_strategy_batch_size 2.0 MiB NULL user NULL 2.0 MiB 2.0 MiB
join_reader_ordering_strategy_batch_size 100 KiB NULL user NULL 100 KiB 100 KiB
-large_full_scan_rows 1000 NULL user NULL 1000 1000
+large_full_scan_rows 0 NULL user NULL 0 0
lc_collate C.UTF-8 NULL user NULL C.UTF-8 C.UTF-8
lc_ctype C.UTF-8 NULL user NULL C.UTF-8 C.UTF-8
lc_messages C.UTF-8 NULL user NULL C.UTF-8 C.UTF-8
diff --git a/pkg/sql/logictest/testdata/logic_test/show_source b/pkg/sql/logictest/testdata/logic_test/show_source
index 5c419ec90171..e1f7f7912ebd 100644
--- a/pkg/sql/logictest/testdata/logic_test/show_source
+++ b/pkg/sql/logictest/testdata/logic_test/show_source
@@ -105,7 +105,7 @@ is_superuser on
join_reader_index_join_strategy_batch_size 4.0 MiB
join_reader_no_ordering_strategy_batch_size 2.0 MiB
join_reader_ordering_strategy_batch_size 100 KiB
-large_full_scan_rows 1000
+large_full_scan_rows 0
lc_collate C.UTF-8
lc_ctype C.UTF-8
lc_messages C.UTF-8
diff --git a/pkg/sql/opt/exec/execbuilder/relational.go b/pkg/sql/opt/exec/execbuilder/relational.go
index 6bfbbd308818..d576fa6039ec 100644
--- a/pkg/sql/opt/exec/execbuilder/relational.go
+++ b/pkg/sql/opt/exec/execbuilder/relational.go
@@ -770,7 +770,7 @@ func (b *Builder) buildScan(scan *memo.ScanExpr) (_ execPlan, outputCols colOrdM
relProps := scan.Relational()
stats := relProps.Statistics()
if !tab.IsVirtualTable() && isUnfiltered {
- large := !stats.Available || stats.RowCount > b.evalCtx.SessionData().LargeFullScanRows
+ large := !stats.Available || stats.RowCount >= b.evalCtx.SessionData().LargeFullScanRows
if scan.Index == cat.PrimaryIndex {
b.flags.Set(exec.PlanFlagContainsFullTableScan)
if large {