sybase ase延迟更新模式
sybase ase deferred update mode
我需要一些关于以下更新的优化器选择的帮助。我希望直接更新,而不是延迟更新。
在现实生活中,这涉及一个包含约 500 万行的目标 table,该目标是从约 20 万行的较小 table 更新而来的。延迟更新需要一些时间,这也是因为目标 table 有大约 60 列。
非常欢迎任何解释此行为的建议,包括改进此查询性能的建议。较小的 table 可以轻松修改,对目标 table 的更改影响更大,因为它是产品数据模型的一部分。
非常感谢!
埃尔罗伊
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
更新,您需要让 table 在查询计划中排在第一位……不过,理想情况下,在这种情况下,优化器应该能够弄清楚 a) 您要加入基于 2 个唯一索引的 tables(即保证有 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.
这是否是 better/faster 延迟更新将取决于必须从 tt 扫描的行的数量加上到 tf1 和 tf2 的连接数。
另外请记住,如果您在 table 上有触发器,或者您发现自己正在更新索引列,再多的技巧也无济于事。
如果有"worst answer"奖励可以给我。我曾经在 Sybase 担任高级顾问,我得出的结论是直接更新不值得花时间让它工作。如果您关心的是性能,我会建议使用应用程序或存储过程来执行批量更新。在更新源上放置一个 ID table 并更新 ID 为 1 到 5000、2 到 5001 等的位置。我个人的经验是,这会让您物有所值。
另外,你查过直接更新的规则了吗?它们比我那个时代更宽松,任何 NULL 或可变大小 (varchar) 列的更新都会使更新延迟,但仍然相当严格:http://infocenter.sybase.com/help/index.jsp?topic=/com.sybase.infocenter.dc00743.1502/html/queryprocessing/queryprocessing29.htm .
我是新来的 - 是否应该以不同的方式发布,因为它实际上不是请求的解决方案?
我需要一些关于以下更新的优化器选择的帮助。我希望直接更新,而不是延迟更新。
在现实生活中,这涉及一个包含约 500 万行的目标 table,该目标是从约 20 万行的较小 table 更新而来的。延迟更新需要一些时间,这也是因为目标 table 有大约 60 列。
非常欢迎任何解释此行为的建议,包括改进此查询性能的建议。较小的 table 可以轻松修改,对目标 table 的更改影响更大,因为它是产品数据模型的一部分。
非常感谢!
埃尔罗伊
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
更新,您需要让 table 在查询计划中排在第一位……不过,理想情况下,在这种情况下,优化器应该能够弄清楚 a) 您要加入基于 2 个唯一索引的 tables(即保证有 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.
这是否是 better/faster 延迟更新将取决于必须从 tt 扫描的行的数量加上到 tf1 和 tf2 的连接数。
另外请记住,如果您在 table 上有触发器,或者您发现自己正在更新索引列,再多的技巧也无济于事。
如果有"worst answer"奖励可以给我。我曾经在 Sybase 担任高级顾问,我得出的结论是直接更新不值得花时间让它工作。如果您关心的是性能,我会建议使用应用程序或存储过程来执行批量更新。在更新源上放置一个 ID table 并更新 ID 为 1 到 5000、2 到 5001 等的位置。我个人的经验是,这会让您物有所值。
另外,你查过直接更新的规则了吗?它们比我那个时代更宽松,任何 NULL 或可变大小 (varchar) 列的更新都会使更新延迟,但仍然相当严格:http://infocenter.sybase.com/help/index.jsp?topic=/com.sybase.infocenter.dc00743.1502/html/queryprocessing/queryprocessing29.htm .
我是新来的 - 是否应该以不同的方式发布,因为它实际上不是请求的解决方案?