sql-update - sybase ase 延迟更新模式
问题描述
对于以下更新,我可以使用一些关于优化器选择的帮助。我希望直接更新,而不是延迟更新。
在现实生活中,这涉及一个包含约 5M 行的目标表,该目标表是从一个具有约 200k 行的较小表中更新的。延迟更新需要一些时间才能退出,这也是因为目标表有大约 60 列。
非常欢迎任何解释此行为的建议,包括提高此查询性能的建议。较小的表可以轻松修改,对目标表的更改会产生更大的影响,因为它是产品数据模型的一部分。
非常感谢!
埃尔罗伊
select @@version --Adaptive Server Enterprise/15.5/EBF 18158 SMP ESD#2/P/X64/Windows Server/asear155/2514/64-bit/OPT/Wed Aug 25 05:39:57 2010
IF OBJECT_ID('test_target') IS NOT NULL
DROP TABLE test_target
GO
CREATE TABLE test_target (
id numeric(15,0) IDENTITY NOT NULL,
col1 numeric(15,0) NOT NULL,
col2 char(15) NOT NULL,
CONSTRAINT PK_test_target PRIMARY KEY CLUSTERED(id)
)
LOCK DATAPAGES
go
insert into test_target select 1, '123'
insert into test_target select 1, '456'
go
IF OBJECT_ID('test_from') IS NOT NULL
DROP TABLE test_from
GO
CREATE TABLE test_from (
from_id numeric(15,0) NOT NULL,
from_col2 char(15) NOT NULL
)
LOCK ALLPAGES
GO
insert into test_from select 1,'1'
go
create unique clustered index k1 on test_from (from_id)
go
set showplan on
go
update test_target
set col2 = from_col2
from test_target
join test_from on from_id = id
set showplan off
go
QUERY PLAN FOR STATEMENT 1 (at line 1).
STEP 1
The type of query is UPDATE.
4 operator(s) under root
|ROOT:EMIT Operator (VA = 4)
|
| |UPDATE Operator (VA = 3)
| | The update mode is deferred.
| |
| | |NESTED LOOP JOIN Operator (VA = 2) (Join Type: Inner Join)
| | |
| | | |SCAN Operator (VA = 0)
| | | | FROM TABLE
| | | | test_from
| | | | Table Scan.
| | | | Forward Scan.
| | | | Positioning at start of table.
| | | | Using I/O Size 16 Kbytes for data pages.
| | | | With LRU Buffer Replacement Strategy for data pages.
| | |
| | | |SCAN Operator (VA = 1)
| | | | FROM TABLE
| | | | test_target
| | | | Using Clustered Index.
| | | | Index : PK_test_target
| | | | Forward Scan.
| | | | Positioning by key.
| | | | Keys are:
| | | | id ASC
| | | | Using I/O Size 16 Kbytes for index leaf pages.
| | | | With LRU Buffer Replacement Strategy for index leaf pages.
| | | | Using I/O Size 16 Kbytes for data pages.
| | | | With LRU Buffer Replacement Strategy for data pages.
| |
| | TO TABLE
| | test_target
| | Using I/O Size 16 Kbytes for data pages.
解决方案
一般来说,要获得direct
更新,您需要先将要更新的表放在查询计划中......但是,理想情况下,在这种情况下,优化器应该能够弄清楚 a) 您正在加入基于表的表2 个唯一索引(即,保证具有 1 对 1 匹配)因此 b)direct
更新将是可取的。
有几种方法可以获得direct
更新......假设您不想将查询包装在一对set forceplan on/off
命令中,并且您不想添加抽象查询计划(AQP - 优化器提示),您可以尝试类似:
-- for test purposes, make sure optimizer isn't re-using query plan from previous test run
set statement_cache off
go
set showplan on
go
update test_target
-- push the join into a sub-query
set tt.col2 = (select tf1.from_col2 from test_from tf1 where tf1.from_id = tt.id)
from test_target tt
where -- only process tt rows that have a match in tf2
exists(select 1 from test_from tf2 where tf2.from_id = tt.id)
go
STEP 1
The type of query is UPDATE.
8 operator(s) under root
|ROOT:EMIT Operator (VA = 8)
|
| |UPDATE Operator (VA = 7)
| | The update mode is direct.
| |
| | |SQFILTER Operator (VA = 6) has 2 children.
| | |
| | | |NESTED LOOP JOIN Operator (VA = 3) (Join Type: Inner Join)
| | | |
| | | | |GROUP SORTED Operator (VA = 1)
| | | | |Distinct
| | | | |
| | | | | |SCAN Operator (VA = 0)
| | | | | | FROM TABLE
| | | | | | test_from
| | | | | | tf2
| | | | | | Table Scan.
| | | | | | Forward Scan.
| | | | | | Positioning at start of table.
| | | | | | Using I/O Size 2 Kbytes for data pages.
| | | | | | With LRU Buffer Replacement Strategy for data pages.
| | | |
| | | | |SCAN Operator (VA = 2)
| | | | | FROM TABLE
| | | | | test_target
| | | | | tt
| | | | | Using Clustered Index.
| | | | | Index : PK_test_target
| | | | | Forward Scan.
| | | | | Positioning by key.
| | | | | Keys are:
| | | | | id ASC
| | | | | Using I/O Size 2 Kbytes for index leaf pages.
| | | | | With LRU Buffer Replacement Strategy for index leaf pages.
| | | | | Using I/O Size 2 Kbytes for data pages.
| | | | | With LRU Buffer Replacement Strategy for data pages.
| | |
| | | Run subquery 1 (at nesting level 1).
| | |
| | | QUERY PLAN FOR SUBQUERY 1 (at nesting level 1 and at line 11).
| | |
| | | Correlated Subquery.
| | | Subquery under an EXPRESSION predicate.
| | |
| | | |SCALAR AGGREGATE Operator (VA = 5)
| | | | Evaluate Ungrouped ONCE AGGREGATE.
| | | |
| | | | |SCAN Operator (VA = 4)
| | | | | FROM TABLE
| | | | | test_from
| | | | | tf1
| | | | | Using Clustered Index.
| | | | | Index : k1
| | | | | Forward Scan.
| | | | | Positioning by key.
| | | | | Keys are:
| | | | | from_id ASC
| | | | | Using I/O Size 2 Kbytes for data pages.
| | | | | With LRU Buffer Replacement Strategy for data pages.
| | |
| | | END OF QUERY PLAN FOR SUBQUERY 1.
| |
| | TO TABLE
| | test_target
| | Using I/O Size 2 Kbytes for data pages.
这是否比延迟更新更好/更快将取决于必须从 tt 扫描的行数加上到 tf1 和 tf2 的连接数。
还要记住,如果您在表上有触发器,或者您发现自己正在更新索引列,那么再多的技巧也无济于事。
推荐阅读
- r - 从随机日期开始的(下)月末
- python - 如何组合并从多个表中获取单个 id 的数据
- rust - 为什么 AtomicPtr 不允许动态大小的类型?
- python - 将烧瓶应用程序部署到 Elastic Beanstalk 时遇到问题
- laravel - 拉拉维尔 | 如何在类别视图中显示分配给产品的属性
- c# - 获取和显示大量数据的最佳实践
- sql - us WHERE 语句和 AthenaQuery 的 ARRAY
- wordpress - 如何将 Yoast SEO 插件数据传输到高级自定义字段
- android - DatePicker 对话框未在单击时显示
- ios - 如何在 iOS 中将大文件块明智地上传到 Azure blob 时减少内存使用量?