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 .

我是新来的 - 是否应该以不同的方式发布,因为它实际上不是请求的解决方案?