数据库其它

关注公众号 jb51net

关闭
首页 > 数据库 > 数据库其它 > 达梦数据库查询较慢

达梦数据库查询较慢的快速诊断及优化

作者:百代繁华一朝都-绮罗生

在达梦数据库中,慢SQL查询不仅会影响系统的性能,还会降低用户体验,这篇文章主要介绍了达梦数据库查询较慢的快速诊断及优化的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下

1 快速诊断:定位瓶颈所在

1.1 查看当前慢SQL

– 最慢的 20 条 SQL 统计

SELECT TOP 20 START_TIME,TIME_USED/1000 TIME_USED,TOP_SQL_TEXT FROM V$SQL_HISTORY ORDER BY TIME_USED DESC;
SELECT * FROM V$SYSTEM_LONG_EXEC_SQLS ORDER BY EXEC_TIME DESC;

–查询慢 SQL 及阻塞

SELECT
        DS.SESS_ID "被阻塞的会话ID",
        DS.SQL_TEXT "被阻塞的SQL",
        DS.TRX_ID "被阻塞的事务ID",
        (CASE L.LTYPE WHEN 'OBJECT' THEN '对象锁' WHEN 'TID' THEN '事务锁' END CASE ) "被阻塞的锁类型",
        DS.CREATE_TIME "开始阻塞时间",
        SS.SESS_ID "占用锁的会话ID",
        SS.SQL_TEXT "占用锁的SQL",
        SS.CLNT_IP "占用锁的IP",
        L.TID "占用锁的事务ID"
FROM
        V$LOCK L
LEFT JOIN V$SESSIONS DS
ON
        DS.TRX_ID = L.TRX_ID
LEFT JOIN V$SESSIONS SS
ON
        SS.TRX_ID = L.TID
WHERE
        L.BLOCKED = 1;

1.2 检查系统资源状态

– 查看缓存命中率

数据缓冲区是 DMSERVER 在将数据页写入磁盘之前以及从磁盘上读取数据页之后,数据页所存储的地方。

数据缓冲区设定得太小,会导致缓冲页命中率低,磁盘 IO 频繁;将其设定得太大,又会导致操作系统内存本身不够用。

select
      name 缓冲池名称,
      sum(page_size)*sf_get_page_size 缓冲池大小_G,
      sum(rat_hit) /count(*) 命中率
from
      v$bufferpool
group by name;

2 SQL语句优化

2.1 分析执行计划

– 对慢SQL生成执行计划

EXPLAIN SELECT * FROM your_table WHERE your_conditions;

执行计划重点关注:

是否使用了合适的索引(INDEX SCAN)

避免全表扫描(CROSS INDEX SCAN)

注意排序操作(SORT)是否必要

2.2 常见SQL优化技巧

– 避免 SELECT *,只取需要的字段

SELECT id, name FROM users WHERE status = 1;  -- 好
SELECT * FROM users WHERE status = 1;         -- 差

– 为查询条件字段添加索引

CREATE INDEX idx_users_status ON users(status);

– 避免在WHERE条件中对字段进行函数操作

SELECT * FROM orders WHERE DATE_FORMAT(create_time, '%Y-%m') = '2024-01';  -- 差
SELECT * FROM orders WHERE create_time >= '2024-01-01' AND create_time < '2024-02-01';  -- 好

– 使用EXISTS代替IN(大数据量时)

SELECT * FROM table1 WHERE EXISTS (
    SELECT 1 FROM table2 WHERE table1.id = table2.id
);

3. 索引优化策略

3.1 检查缺失索引

– 查找可能需要索引的表

3.2 创建合适的索引

在以下场景下可考虑创建索引:

仅当要通过索引访问表中很少的一部分行(1%~20%)。
索引可覆盖查询所需的所有列,不需额外去访问表。

存在下列情况将导致无法使用索引:

组合索引中,条件列中没有组合索引的首列。
条件列带有函数或计算。
索引排序是按照字段值进行排序的,字段值通过函数或计算后的值索引无法获取。
索引过滤性能不好时。

4. 数据库参数优化

4.1 关键性能参数检查

内存相关
BUFFER = 10000 # 缓冲区大小(MB),建议系统内存的50-70%
MAX_BUFFER = 10000 # 最大缓冲区
SORT_BUF_SIZE = 200 # 排序缓冲区(MB)
HJ_BUF_SIZE = 200 # HASH连接缓冲区(MB)

#并行处理
PARALLEL_POLICY = 1 # 启用并行
PARALLEL_THREAD_NUM = 4 # 并行线程数

#优化器相关
OPTIMIZER_MODE = 1 # 优化器模式

5. 统计信息维护

5.1 更新统计信息

– 更新表的统计信息

CALL SP_TAB_STAT_INIT('SCHEMA_NAME', 'TABLE_NAME');

– 更新整个模式的统计信息

CALL SP_DB_STAT_INIT('SCHEMA_NAME');

– 收集列统计信息

CALL SP_COL_STAT_INIT('SCHEMA_NAME', 'TABLE_NAME', 'COLUMN_NAME');

5.2 定期维护脚本

举例:

– 更新模式 DB_TEST 下的统计信息

DBMS_STATS.GATHER_SCHEMA_STATS('DB_TEST', 100, TRUE, 'FOR ALL COLUMNS SIZE AUTO');

– 更新特定表的统计信息

DBMS_STATS.GATHER_TABLE_STATS('username', 'table_name', null, 100, TRUE, 'FOR ALL COLUMNS SIZE AUTO', cascade => true, degree => 8);

– 更新所有表和索引的统计信息并记录日志

drop table if exists my_tab_stats;
create table my_tab_stats(table_name varchar2(100),owner varchar2(100),stat_flag varchar2(5),begin_time timestamp,end_time timestamp);
insert into my_tab_stats(table_name,owner) select table_name,owner from dba_tables where owner in ('OA');
update my_tab_stats set stat_flag = 0;
commit;
begin
    for tb in (select rowid,table_name,owner from my_tab_stats where stat_flag = 0 ) 
	loop
        update my_tab_stats set begin_time=sysdate where my_tab_stats.table_name=tb.table_name and my_tab_stats.owner=tb.owner;
        dbms_stats.gather_table_stats(tb.owner,tb.table_name,null,100,true,'FOR ALL COLUMNS SIZE AUTO',cascade => true, degree => 8);
        update my_tab_stats set stat_flag = 1,end_time=sysdate where my_tab_stats.table_name = tb.table_name and my_tab_stats.owner=tb.owner;
        commit;
    end loop;
end;

6. 架构和设计优化

6.1 分区表优化

– 对大表进行分区
CREATE TABLE sales (
sale_id INT,
sale_date DATE,
amount DECIMAL(10,2)
)
PARTITION BY RANGE(sale_date)
(
PARTITION p2023 VALUES LESS THAN (‘2024-01-01'),
PARTITION p2024 VALUES LESS THAN (‘2025-01-01')
);

6.2 物化视图

– 为复杂查询创建物化视图

CREATE MATERIALIZED VIEW mv_sales_summary
REFRESH COMPLETE ON DEMAND
AS 
SELECT customer_id, SUM(amount) as total_amount,
       COUNT(*) as order_count
FROM sales 
GROUP BY customer_id;

7. 紧急优化措施

如果系统正在经历严重性能问题:

—立即终止阻塞会话:

SP_CLOSE_SESSION(session_id); – 谨慎使用!
—清理缓存:
—重启数据库服务(最后手段)

优化实施建议

总结

到此这篇关于达梦数据库查询较慢的快速诊断及优化的文章就介绍到这了,更多相关达梦数据库查询较慢内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文