oracle-troubleshooting- 如何通过 dba_hist_active_sess_history 分析数据库历史性能问题

简介:

如何通过 dba_hist_active_sess_history 分析数据库历史性能问题

背景

在很多情况下,当数据库发生性能问题的时候,我们并没有机会来收集足够的诊断信息,比如system state dump或者hang analyze,甚至问题发生的时候DBA根本不在场。这给我们诊断问题带来很大的困难。那么在这种情况下,我们是否能在事后收集一些信息来分析问题的原因呢?
在Oracle 10G或者更高版本上,答案是肯定的。本文我们将介绍一种通过dba_hist_active_sess_history的数据来分析问题的一种方法。
AI 代码解读

适用于

Oracle 10G或更高版本的单机或rac,本文适用于任何平台。
AI 代码解读

详情

 Active Session: on the CPU or was waiting for an event that didn't belong to the Idle wait class
在Oracle 10G中,我们引入了AWR和ASH采样机制,有一个视图gv$active_session_history会每秒钟将数据库所有节点的Active Session采样一次,
而dba_hist_active_sess_history则会将gv$active_session_history里的数据每10秒采样一次并持久化保存。
基于这个特征,我们可以通过分析dba_hist_active_sess_history的Session采样情况,来定位问题发生的准确时间范围,并且可以观察每个采样点的top event和top holder。下面通过一个例子来详细说明。
AI 代码解读

dba_hist_active_sess_history版

1. Dump出问题期间的ASH数据:

为了不影响生产系统,我们可以将问题大概期间的ASH数据export出来在测试机上分析。
基于dba_hist_active_sess_history创建一个新表t_ash,然后将其通过exp/imp导入到测试机。在发生问题的数据库上执行exp:
SQL> conn user/passwd
SQL> create table t_ash as select * from dba_hist_active_sess_history where SAMPLE_TIME between TO_TIMESTAMP ('<time_begin>', 'YYYY-MM-DD HH24:MI:SS') and TO_TIMESTAMP ('<time_end>', 'YYYY-MM-DD HH24:MI:SS');

$ exp user/passwd file=t_ash.dmp tables=(t_ash) log=t_ash.exp.log

然后导入到测试机:
$ imp user/passwd file=t_ash.dmp log=t_ash.imp.log
AI 代码解读

2. 验证导出的ASH时间范围:

建议采用Oracle SQL Developer来查询以防止输出结果折行不便于观察。

set line 200 pages 1000
col sample_time for a25
col event for a40
alter session set nls_timestamp_format='yyyy-mm-dd hh24:mi:ss.ff';

select
 t.dbid, t.instance_number, min(sample_time), max(sample_time), count(*) session_count
  from t_ash t
 group by t.dbid, t.instance_number
 order by dbid, instance_number;

INSTANCE_NUMBER    MIN(SAMPLE_TIME)    MAX(SAMPLE_TIME)    SESSION_COUNT
1    2015-03-26 21:00:04.278    2015-03-26 22:59:48.387    2171
2    2015-03-26 21:02:12.047    2015-03-26 22:59:42.584    36

从以上输出可知该数据库共2个节点,采样时间共2小时,节点1的采样比节点2要多很多,问题可能发生在节点1上。
AI 代码解读

3. 确认问题发生的精确时间范围:

参考如下脚本:
col event for a35
set lines 222
set pages 9999
select
 dbid, instance_number, sample_id, sample_time, count(*) session_count
  from t_ash t
 group by dbid, instance_number, sample_id, sample_time
 order by dbid, instance_number, sample_time;

INSTANCE_NUMBER    SAMPLE_ID    SAMPLE_TIME    SESSION_COUNT
1    36402900    2015-03-26 22:02:50.985    4
1    36402910    2015-03-26 22:03:01.095    1
1    36402920    2015-03-26 22:03:11.195    1
1    36402930    2015-03-26 22:03:21.966    21
1    36402940    2015-03-26 22:03:32.116    102
1    36402950    2015-03-26 22:03:42.226    181
1    36402960    2015-03-26 22:03:52.326    200
1    36402970    2015-03-26 22:04:02.446    227
1    36402980    2015-03-26 22:04:12.566    242
1    36402990    2015-03-26 22:04:22.666    259
1    36403000    2015-03-26 22:04:32.846    289
1    36403010    2015-03-26 22:04:42.966    147
1    36403020    2015-03-26 22:04:53.076    2
1    36403030    2015-03-26 22:05:03.186    4
1    36403040    2015-03-26 22:05:13.296    1
1    36403050    2015-03-26 22:05:23.398    1

注意观察以上输出的每个采样点的active session的数量,数量突然变多往往意味着问题发生了。从以上输出可以确定问题发生的精确时间在2015-03-26 22:03:21 ~ 22:04:42,问题持续了大约1.5分钟。
注意: 观察以上的输出有无断档,比如某些时间没有采样。
AI 代码解读

4. 确定每个采样点的top n event:

在这里我们指定的是top 2 event 并且注掉了采样时间以观察所有采样点的情况。如果数据量较多,您也可以通过开启sample_time的注释来观察某个时间段的情况。注意最后一列session_count指的是该采样点上的等待该event的session数量。
col event for a35
set lines 1000
set pages 9999
select t.dbid,
       t.sample_id,
       t.sample_time,
       t.instance_number,
       t.event,
       t.session_state,
       t.c session_count
  from (select t.*,
               rank() over(partition by dbid, instance_number, sample_time order by c desc) r
          from (select /*+ parallel 2 */
                 t.*,
                 count(*) over(partition by dbid, instance_number, sample_time, event) c,
                 row_number() over(partition by dbid, instance_number, sample_time, event order by 1) r1
                  from t_ash t
                /*where sample_time >
                    to_timestamp('2013-11-17 13:59:00',
                                 'yyyy-mm-dd hh24:mi:ss')
                and sample_time <
                    to_timestamp('2013-11-17 14:10:00',
                                 'yyyy-mm-dd hh24:mi:ss')*/
                ) t
         where r1 = 1) t
 where r < 3
 order by dbid, instance_number, sample_time, r;

SAMPLE_ID    SAMPLE_TIME    INSTANCE_NUMBER               EVENT                                SESSION_STATE        SESSION_COUNT
36402900    22:02:50.985            1                ON CPU                                                        3
36402900    22:02:50.985            1           db file sequential read                        WAITING             1
36402910    22:03:01.095            1                ON CPU                                                      1
36402920    22:03:11.195            1             db file parallel read                        WAITING              1
36402930    22:03:21.966            1           cursor: pin S wait on X                        WAITING           11
36402930    22:03:21.966            1                latch: shared pool                         WAITING            4
36402940    22:03:32.116            1           cursor: pin S wait on X                          WAITING           83
36402940    22:03:32.116            1           SGA: allocation forcing component growth         WAITING              16
36402950    22:03:42.226            1           cursor: pin S wait on X                          WAITING          161                       
36402950    22:03:42.226            1           SGA: allocation forcing component growth         WAITING              17
36402960    22:03:52.326            1           cursor: pin S wait on X                         WAITING          177                       
36402960    22:03:52.326            1           SGA: allocation forcing component growth         WAITING              20
36402970    22:04:02.446            1           cursor: pin S wait on X                        WAITING             204                       
36402970    22:04:02.446            1           SGA: allocation forcing component growth         WAITING              20
36402980    22:04:12.566            1           cursor: pin S wait on X                        WAITING          219                       
36402980    22:04:12.566            1           SGA: allocation forcing component growth         WAITING              20
36402990    22:04:22.666            1           cursor: pin S wait on X                         WAITING          236                       
36402990    22:04:22.666            1           SGA: allocation forcing component growth         WAITING              20
36403000    22:04:32.846            1           cursor: pin S wait on X                        WAITING          265                       
36403000    22:04:32.846            1           SGA: allocation forcing component growth         WAITING              20
36403010    22:04:42.966            1           enq: US - contention                             WAITING            69
36403010    22:04:42.966            1           latch: row cache objects                       WAITING            56
36403020    22:04:53.076            1           db file scattered read                         WAITING            1
36403020    22:04:53.076            1           db file sequential read                        WAITING            1

从以上输出我们可以发现问题期间最严重的等待为cursor: pin S wait on X,高峰期等待该event的session数达到了265个,其次为SGA: allocation forcing component growth,高峰期session20个。

***注意:
    1) 再次确认以上输出有无断档,是否有某些时间没有采样。
    2) 注意那些session_state为ON CPU的输出,比较ON CPU的进程个数与您的OS物理CPU的个数,如果接近或者超过物理CPU个数,那么您还需要检查OS当时的CPU资源状况,
       比如OSWatcher/NMON等工具,高的CPU Run Queue可能引发该问题,当然也可能是问题的结果,需要结合OSWatcher和ASH的时间顺序来验证。
AI 代码解读

5. 观察每个采样点的等待链: (更详细显示参考:附1)

其原理为通过dba_hist_active_sess_history. blocking_session记录的holder来通过connect by级联查询,找出最终的holder. 在RAC环境中,每个节点的ASH采样的时间很多情况下并不是一致的,
因此您可以通过将本SQL的第二段注释的sample_time稍作修改让不同节点相差1秒的采样时间可以比较(注意最好也将partition by中的sample_time做相应修改)。
该输出中isleaf=1的都是最终holder,而iscycle=1的代表死锁了(也就是在同一个采样点中a等待b,b等待c,而c又等待a,这种情况如果持续发生,那么尤其值得关注)。采用如下查询能观察到阻塞链。
col event for a35
set lines 1000
set pages 9999
select  /*+ parallel 8 */
 level                     lv,
 connect_by_isleaf         isleaf,
 connect_by_iscycle        iscycle,
 t.dbid,
 t.sample_id,
 t.sample_time,
 t.instance_number,
 t.session_id,
 t.sql_id,
 t.session_type,
 t.event,
 t.session_state,
 t.blocking_inst_id,
 t.blocking_session,
 t.blocking_session_status
  from t_ash t
/*where sample_time >
    to_timestamp('2013-11-17 13:55:00',
                 'yyyy-mm-dd hh24:mi:ss')
and sample_time <
    to_timestamp('2013-11-17 14:10:00',
                 'yyyy-mm-dd hh24:mi:ss')*/
 start with blocking_session is not null
 /*start with event = 'buffer busy waits'*/
connect by nocycle
 prior dbid = dbid
       and prior sample_time = sample_time
          /*and ((prior sample_time) - sample_time between interval '-1'
          second and interval '1' second)*/
       and prior blocking_inst_id = instance_number
       and prior blocking_session = session_id
       and prior blocking_session_serial# = session_serial#
 order siblings by dbid, sample_time;

LV    ISLEAF    ISCYCLE    SAMPLE_TIME    INSTANCE_NUMBER    SESSION_ID         SQL_ID        EVENT          SESSION_STATE    BLOCKING_INST_ID    BLOCKING_SESSION    BLOCKING_SESSION_STATUS
1       0        0           22:04:32.846            1                1259          3ajt2htrmb83y    cursor:           WAITING                1               537                    VALID
2       1        0           22:04:32.846            1                537           3ajt2htrmb83y    SGA:              WAITING                                                       UNKNOWN

***注意:
    为了输出便于阅读,我们将等待event做了简写,下同。从上面的输出可见,在相同的采样点上(22:04:32.846),节点1 session 1259 在等待cursor: pin S wait on X,其被节点1 session 537 阻塞,
    而节点1 session 537 又在等待SGA: allocation forcing component growth,并且ASH没有采集到其holder,因此这里cursor: pin S wait on X只是一个表面现象,
    问题的原因在于SGA: allocation forcing component growth
AI 代码解读

6. 基于第5步的原理来找出每个采样点的最终top holder:

比如如下SQL列出了每个采样点top 2的blocker session,并且计算了其最终阻塞的session数(参考blocking_session_count)
col event for a35
set lines 1000
set pages 9999
select t.lv,
       t.iscycle,
       t.dbid,
       t.sample_id,
       t.sample_time,
       t.instance_number,
       t.session_id,
       t.sql_id,
       t.session_type,
       t.event,
       t.seq#,
       t.session_state,
       t.blocking_inst_id,
       t.blocking_session,
       t.blocking_session_status,
       t.c blocking_session_count
  from (select t.*,
               row_number() over(partition by dbid, instance_number, sample_time order by c desc) r
          from (select t.*,
                       count(*) over(partition by dbid, instance_number, sample_time, session_id) c,
                       row_number() over(partition by dbid, instance_number, sample_time, session_id order by 1) r1
                  from (select
                         level              lv,
                         connect_by_isleaf  isleaf,
                         connect_by_iscycle iscycle,
                         t.*
                          from t_ash t
                        /*where sample_time >
                            to_timestamp('2013-11-17 13:55:00',
                                         'yyyy-mm-dd hh24:mi:ss')
                        and sample_time <
                            to_timestamp('2013-11-17 14:10:00',
                                         'yyyy-mm-dd hh24:mi:ss')*/
                         start with blocking_session is not null
                         /*start with event = 'buffer busy waits'*/
                        connect by nocycle
                         prior dbid = dbid
                               and prior sample_time = sample_time
                                  /*and ((prior sample_time) - sample_time between interval '-1'
                                  second and interval '1' second)*/
                               and prior blocking_inst_id = instance_number
                               and prior blocking_session = session_id
                               and prior
                                    blocking_session_serial# = session_serial#) t
                 where t.isleaf = 1) t
         where r1 = 1) t
 where r < 3
 order by dbid, sample_time, r;

SAMPLE_TIME    INSTANCE_NUMBER    SESSION_ID    SQL_ID         EVENT    SEQ#    SESSION_STATE    BLOCKING_SESSION_STATUS    BLOCKING_SESSION_COUNT
22:03:32.116           1               1136        1p4vyw2jan43d    SGA:    1140       WAITING                UNKNOWN                        82
22:03:32.116           1               413         9g51p4bt1n7kz    SGA:    7646       WAITING                UNKNOWN                        2
22:03:42.226           1               1136        1p4vyw2jan43d    SGA:    1645       WAITING                UNKNOWN                        154
22:03:42.226           1               537         3ajt2htrmb83y    SGA:    48412      WAITING                UNKNOWN                        4
22:03:52.326           1               1136        1p4vyw2jan43d    SGA:    2150       WAITING                UNKNOWN                        165
22:03:52.326           1               537         3ajt2htrmb83y    SGA:    48917      WAITING                UNKNOWN                        8
22:04:02.446           1               1136        1p4vyw2jan43d    SGA:    2656       WAITING                UNKNOWN                        184
22:04:02.446           1               537         3ajt2htrmb83y    SGA:    49423      WAITING                UNKNOWN                        10
22:04:12.566           1               1136        1p4vyw2jan43d    SGA:    3162       WAITING                UNKNOWN                        187
22:04:12.566           1               2472                          SGA:    1421       WAITING                UNKNOWN                        15
22:04:22.666           1               1136        1p4vyw2jan43d    SGA:    3667       WAITING                UNKNOWN                        193
22:04:22.666           1               2472                          SGA:    1926       WAITING                UNKNOWN                        25
22:04:32.846           1                   1136        1p4vyw2jan43d    SGA:    4176       WAITING                UNKNOWN                        196
22:04:32.846           1               2472                           SGA:    2434       WAITING                UNKNOWN                        48

从以上输出,比如第一行,代表在22:03:32.116,节点1session 1136 最终阻塞了82session.  顺着时间往下看,可见节点1session 1136 是问题期间最严重的holder,
它在每个采样点都阻塞了100多个session,并且它持续等待SGA: allocation forcing component growth,
注意观察其seq#您会发现该event的seq#在不断变化,表明该session并未完全hang住,由于时间正好发生在夜间22:00左右,这显然是由于自动收集统计信息job导致shared memory resize造成,
因此可以结合Scheduler/MMAN的trace以及dba_hist_memory_resize_ops的输出进一步确定问题。
**注意:
    1) blocking_session_count 指某一个holder最终阻塞的session数,比如 a <- b<- c (a被b阻塞,b又被c阻塞),只计算c阻塞了1session,因为中间的b可能在不同的阻塞链中发生重复。
    2) 如果最终的holder没有被ash采样(一般因为该holder处于空闲),比如 a<- c 并且b<- c (a被c阻塞,并且b也被c阻塞),但是c没有采样,那么以上脚本无法将c统计到最终holder里,这可能会导致一些遗漏。
    3) 注意比较blocking_session_count的数量与第3步查询的每个采样点的总session_count数,如果每个采样点的blocking_session_count数远小于总session_count数,那表明大部分session并未记载holder,因此本查询的结果并不能代表什么。
    4) 在Oracle 10g中,ASH并没有blocking_inst_id列,在以上所有的脚本中,您只需要去掉该列即可,因此10g的ASH一般只能用于诊断单节点的问题。
AI 代码解读

**
**

其他关于ASH的应用

除了通过ASH数据来找holder以外,我们还能用它来获取很多信息(基于数据库版本有所不同):
比如通过PGA_ALLOCATED列来计算每个采样点的最大PGA,合计PGA以分析ora-4030/Memory Swap相关问题;
通过TEMP_SPACE_ALLOCATED列来分析临时表空间使用情况;
通过IN_PARSE/IN_HARD_PARSE/IN_SQL_EXECUTION列来分析SQL处于parse还是执行阶段;
通过CURRENT_OBJ#/CURRENT_FILE#/CURRENT_BLOCK#来确定I/O相关等待发生的对象.




AI 代码解读

附1:

set lines 1000
set pages 9999
select /*+ parallel 8 */
level lv,
connect_by_isleaf isleaf,
connect_by_iscycle     iscycle,
t.dbid,
t.sample_id,
t.sample_time,
t.instance_number,
t.session_id,
t.session_serial#,
t.session_type,
t.session_state,
t.SQL_OPNAME,
t.sql_id,
T.SQL_PLAN_HASH_VALUE,
t.SQL_PLAN_LINE_ID,
T.SQL_CHILD_NUMBER,
T.SQL_EXEC_ID,
T.SQL_EXEC_START,
T.IN_BIND,
t.IN_PARSE,
t.IN_HARD_PARSE,
t.IN_SQL_EXECUTION,
t.IN_PLSQL_COMPILATION,
t.IN_PLSQL_EXECUTION,
t.IN_SEQUENCE_LOAD,
T.IN_PLSQL_RPC,
t.PROGRAM,
t.MACHINE,
t.PGA_ALLOCATED,
t.TEMP_SPACE_ALLOCATED,
t.DELTA_READ_IO_BYTES,
t.DELTA_WRITE_IO_BYTES,
t.TM_DELTA_CPU_TIME,
t.event,
t.blocking_inst_id,
t.blocking_session,
t.blocking_session_serial#,
t.blocking_session_status,
t.WAIT_TIME,
t.TIME_WAITED,
t.CURRENT_OBJ#,
t.CURRENT_ROW#,
t.xid
from m_ash_202204162 t
start with event = 'buffer busy waits'
--start with blocking_session is not null
connect by nocycle prior dbid = dbid and prior blocking_session = session_id and prior blocking_session_serial# = session_serial#
and prior sample_time = sample_time and prior blocking_inst_id = instance_number  order siblings by dbid, sample_time;
AI 代码解读

附2: 查看某个具体session的采样等待信息

set lines 1000
set pages 9999
select /*+ parallel 4 */
t.dbid,
t.sample_id,
t.sample_time,
t.instance_number,
t.session_id,
t.session_serial#,
t.session_type,
t.session_state,
t.SQL_OPNAME,
t.sql_id,
T.SQL_PLAN_HASH_VALUE,
t.SQL_PLAN_LINE_ID,
T.SQL_CHILD_NUMBER,
T.SQL_EXEC_ID,
T.SQL_EXEC_START,
T.IN_BIND,
t.IN_PARSE,
t.IN_HARD_PARSE,
t.IN_SQL_EXECUTION,
t.IN_PLSQL_COMPILATION,
t.IN_PLSQL_EXECUTION,
t.IN_SEQUENCE_LOAD,
T.IN_PLSQL_RPC,
t.PROGRAM,
t.MACHINE,
t.PGA_ALLOCATED,
t.TEMP_SPACE_ALLOCATED,
t.DELTA_READ_IO_BYTES,
t.DELTA_WRITE_IO_BYTES,
t.TM_DELTA_CPU_TIME,
t.event,
t.blocking_inst_id,
t.blocking_session,
t.blocking_session_serial#,
t.blocking_session_status,
t.WAIT_TIME,
t.TIME_WAITED,
t.CURRENT_OBJ#,
t.CURRENT_ROW#,
t.xid
from m_ash_202204162 t
where session_id = 10501
order by dbid, instance_number,sample_time;
AI 代码解读

附3:查看Sql文本

select * from dba_hist_sqltext where sql_id='bxgrjr8wa7g7x';
        
AI 代码解读

附4:查看sql执行详细信息参考文档:

分析sql历史执行信息.md
相关文章
【Oracle】使用Navicat Premium连接Oracle数据库两种方法
以上就是两种使用Navicat Premium连接Oracle数据库的方法介绍,希望对你有所帮助!
132 28
【赵渝强老师】Oracle的闪回数据库
Oracle闪回数据库功能类似于“倒带按钮”,可快速将数据库恢复至 earlier 状态,无需还原备份。本文介绍了闪回数据库的使用方法及实战案例:包括设置归档模式、开启闪回功能、记录SCN号、执行误操作后的恢复步骤等。通过具体 SQL 操作演示了如何利用闪回数据库恢复被误删的用户数据。注意,使用此功能前需确保数据库为归档模式。
【赵渝强老师】Oracle数据库的闪回表
本文介绍了Oracle数据库中的闪回表(Flashback Table)功能,它能够将表的数据快速恢复到特定时间点或系统改变号(SCN),无需备份。文章通过实战示例详细演示了如何使用闪回表恢复数据,包括授权、创建测试表、记录时间与SCN号、删除数据、启用行移动功能、执行闪回操作以及验证恢复结果等步骤。同时,还展示了如何通过触发器禁止插入操作,并在闪回过程中处理触发器的启用问题。文末附有视频讲解,帮助读者更好地理解闪回表的使用方法。
70 10
【赵渝强老师】Oracle数据库的闪回查询
本文介绍了Oracle数据库的闪回查询(Flashback Query)功能及其实际应用。闪回查询通过`AS OF`子句,结合时间戳或SCN号,可查询历史数据状态,帮助分析数据差异。文中通过具体示例演示了如何使用闪回查询:创建测试表、记录当前SCN号、更新数据并提交事务,最后通过闪回查询获取历史数据。附带的视频和代码块详细展示了操作步骤与结果。
【赵渝强老师】Oracle数据库的闪回技术
在Oracle数据库操作中,难免会遇到误删表或提交错误事务等问题,可能导致数据丢失甚至数据库停止运行。传统解决方法依赖备份恢复,但需提前准备正确备份。为此,Oracle提供了闪回技术,无需备份即可快速恢复数据。它支持7种类型的操作,如闪回查询、版本查询、表恢复等,能有效应对逻辑损坏和用户错误。闪回技术基于还原(undo)数据管理,启用自动管理后可实现高效恢复。
【赵渝强老师】Oracle数据库的客户端工具
本文介绍了Oracle数据库的三种客户端工具:SQL*Plus、Oracle Enterprise Manager Database Express(EM)和SQL Developer的使用方法。首先通过命令行工具SQL*Plus登录数据库,创建用户并授权,建立部门与员工表,插入数据并查询;接着讲解了如何通过浏览器访问EM界面监控数据库及表空间状态;最后演示了SQL Developer的下载安装、连接配置以及执行查询的过程,帮助用户快速上手Oracle数据库管理与操作。
如何优化SQL查询以提高数据库性能?
这篇文章以生动的比喻介绍了优化SQL查询的重要性及方法。它首先将未优化的SQL查询比作在自助餐厅贪多嚼不烂的行为,强调了只获取必要数据的必要性。接着,文章详细讲解了四种优化策略:**精简选择**(避免使用`SELECT *`)、**专业筛选**(利用`WHERE`缩小范围)、**高效联接**(索引和限制数据量)以及**使用索引**(加速搜索)。此外,还探讨了如何避免N+1查询问题、使用分页限制结果、理解执行计划以及定期维护数据库健康。通过这些技巧,可以显著提升数据库性能,让查询更高效流畅。
时序数据库 InfluxDB 3.0 版本性能实测报告:写入吞吐量提升效果验证
TSBS 测试表明,对于少于 100 万台设备的数据集,InfluxDB OSS 3.0 的数据写入速度实际上比 InfluxDB OSS 1.8 更慢。 对于 100 万台及以上设备的数据集,InfluxDB OSS 3.0 的数据写入性能才开始超过 InfluxDB OSS 1.8。 InfluxDB OSS 3.0 的数据写入接口与 InfluxDB 1.8 并不兼容,用户无法顺利迁移。
70 7
从 MongoDB 到 时序数据库 TDengine,沃太能源实现 18 倍写入性能提升
沃太能源是国内领先储能设备生产厂商,数十万储能终端遍布世界各地。此前使用 MongoDB 存储时序数据,但随着设备测点增加,MongoDB 在存储效率、写入性能、查询性能等方面暴露出短板。经过对比,沃太能源选择了专业时序数据库 TDengine,生产效能显著提升:整体上,数据压缩率超 10 倍、写入性能提升 18 倍,查询在特定场景上也实现了数倍的提升。同时减少了技术架构复杂度,实现了零代码数据接入。本文将对 TDengine 在沃太能源的应用情况进行详解。
51 0
崖山异构数据库迁移利器YMP初体验-Oracle迁移YashanDB
文章是作者小草对崖山异构数据库迁移利器 YMP 的初体验分享,包括背景、YMP 简介、体验环境说明、YMP 部署(含安装前准备、安装、卸载、启动与停止)、数据迁移及遇到的问题与解决过程。重点介绍了 YMP 功能、部署的诸多细节和数据迁移流程,还提到了安装和迁移中遇到的问题及解决办法。

推荐镜像

更多
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等