【问题标题】:Sybase ASE: Why "SELECT COUNT(*) FROM table" takes many minutesSybase ASE:为什么“SELECT COUNT(*) FROM table”需要很多分钟
【发布时间】:2021-06-15 06:05:15
【问题描述】:

我们在 SuSE Linux 上的 Sybase ASE 16.0 中有一个不断增长的表,其中包含约 1800 万行,其中有两个索引:

create INDEX ind_ig_bigstrings on ig_bigstrings(id,seq_id)
create INDEX ig_bigstrings_syb_id_col on ig_bigstrings( SYB_IDENTITY_COL )

select count(*) from ig_bigstrings 大约需要 5 分钟,第二次运行只需 3 秒。计划显示使用了索引:

1> select count(*) from ig_bigstrings
2> go

QUERY PLAN FOR STATEMENT 1 (at line 1).
Optimized using Serial Mode


    STEP 1
        The type of query is SELECT.

    2 operator(s) under root

       |ROOT:EMIT Operator (VA = 2)
       |
       |   |SCALAR AGGREGATE Operator (VA = 1)
       |   |  Evaluate Ungrouped COUNT AGGREGATE.
       |   |
       |   |   |SCAN Operator (VA = 0)
       |   |   |  FROM TABLE
       |   |   |  ig_bigstrings
       |   |   |  Index : ind_ig_bigstrings
       |   |   |  Forward Scan.
       |   |   |  Positioning at index start.
       |   |   |  Index contains all needed columns. Base table will not be read.
       |   |   |  Using I/O Size 4 Kbytes for index leaf pages.
       |   |   |  With LRU Buffer Replacement Strategy for index leaf pages.


             
 ----------- 
    18917916 

为什么扫描索引需要这么长时间?

顺便说一句:我将同一张表加载到 PostgreSQL 13.1 服务器中,当索引不存在时,操作只需 15 秒,创建索引后只需 2 秒。

【问题讨论】:

  • 第一个猜测:第一次查询必须从磁盘中提取索引,并且磁盘读取时间在这台机器上(相对)慢;第二个猜测:第一个查询被另一个持有所需索引的排他锁的进程阻塞;没有监控数据很难说(例如,MDA 表、sp_lock、sp_who 等)

标签: sql performance sap-ase


【解决方案1】:

一般来说,这可能是由于几个原因(并非详尽的列表):

  1. 表或其索引可能非常分散,这将导致其(派生的)统计数据非常低。
  2. 磁盘设备上的 I/O 争用或一般的磁盘 I/O 缓慢。
  3. 默认数据缓存大小不足以处理数据量。
  4. 大型 I/O 池丢失或大小不足,导致查询优化器选择常规 I/O 池。
  5. 表中有很多转发的行。

查看查询计划,场景 1 似乎不太可能,因为这会导致查询优化器优先选择表扫描而不是索引遍历。使用“更新统计”语句 更新表和/或索引统计信息或使用'reorg rebuild''drop index''create index' 来改进派生统计信息。

系统上的其他进程也会感受到 I/O 争用或缓慢的磁盘 I/O,因此这可能是一个值得关注的问题。

通常一个或多个表格行会很好地适合单个页面。但是,由于在单个行中通常有空间容纳非整数行 页,Sybase ASE 将尝试在单个页面中容纳尽可能多的这些行。任何不适合的都被写入单独的页面,对于哪个 参考被放置在原始页面上。这称为转发行,其中很多对性能有害。如果桌子是 最近创建和/或内容没有太大变化,因为转发的行数将非常少。然而,如果有 对表进行大量插入、删除或更新,这个数字会随着时间的推移稳步增长。使用'reorg forwarded rows' 来改善这一点。

但是,对我来说,最可能的原因是情况 3 或 4,或者这两种情况的组合。特别是因为查询计划告诉我们它是 使用 4 KB 的 I/O 大小。大型 I/O 池的页面大小通常是物理页面大小的 8 倍(用于 安装 Sybase ASE)。对于 2K(最小)页面大小,这将是 16K,对于 8K 页面大小,这将是 64K,依此类推。来自 查询计划文本我认为此服务器使用 4K 页面大小。采用: sp_cacheconfig "<cache name>", "<size>" 设置新的数据缓存或 增长数据缓存(总是有一个“默认数据缓存”,这通常是一个很好的选择)。下一步设置或增加大型 I/O 池 通过运行sp_poolconfig "<cache name>", "<size>", "<page size>" 在此数据缓存中。在上述情况下,我会使用 32K 的大 I/O 页面大小。

【讨论】:

    猜你喜欢
    • 2014-12-12
    • 1970-01-01
    • 2014-12-02
    • 1970-01-01
    • 2012-04-29
    • 2015-05-15
    • 2010-09-16
    • 2023-01-30
    • 1970-01-01
    相关资源
    最近更新 更多