一、性能优化要从哪里入手
很多DBA刚接触DM数据库时,经常会遇到查询慢、系统卡顿的问题。其实性能优化就像看病一样,得先找到病因才能对症下药。我建议从这几个方面入手:
首先得看看SQL语句写得怎么样。很多性能问题其实都是SQL写得不够优雅导致的。比如有个同事写了这样的查询:
-- 错误示例:全表扫描+未使用索引
SELECT * FROM orders WHERE YEAR(create_time) = 2023;
-- 优化后:使用索引范围查询
SELECT * FROM orders
WHERE create_time >= '2023-01-01' AND create_time < '2024-01-01';
其次要关注索引设计。DM数据库的索引和Oracle很像,但有些细节差异。比如复合索引的顺序就很有讲究:
-- 好的索引设计示例
CREATE INDEX idx_user_order ON orders(user_id, status, create_time);
-- 这样查询就能用上索引
SELECT * FROM orders
WHERE user_id = 1001 AND status = 'completed'
ORDER BY create_time DESC;
二、SQL调优的实战技巧
SQL调优是DM数据库优化的核心。这里分享几个实用技巧:
第一个是避免全表扫描。DM的优化器有时候不太智能,需要人工干预:
-- 不好的写法
SELECT * FROM products WHERE price/100 > 10;
-- 优化写法
SELECT * FROM products WHERE price > 1000;
第二个是注意连接查询的方式。DM支持多种连接算法,但性能差异很大:
-- 嵌套循环连接适合小表驱动大表
SELECT /*+ USE_NL(a b) */ a.*, b.*
FROM small_table a, large_table b
WHERE a.id = b.id;
-- 哈希连接适合等值连接的大表
SELECT /*+ USE_HASH(a b) */ a.*, b.*
FROM table_a a, table_b b
WHERE a.key = b.key;
第三个是善用执行计划。DM提供了详细的执行计划分析工具:
-- 查看执行计划
EXPLAIN PLAN FOR
SELECT * FROM orders WHERE user_id = 1001;
-- 显示执行计划
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);
三、系统参数调优的门道
DM数据库有很多隐藏的性能开关,合理配置能带来显著提升:
首先是内存参数。DM使用缓冲池机制,类似Oracle的SGA:
-- 查看当前内存配置
SELECT * FROM V$PARAMETER
WHERE NAME LIKE '%BUFFER%';
-- 建议调整(单位MB)
ALTER SYSTEM SET BUFFER_POOL_SIZE = 4096;
其次是并发参数。根据服务器配置调整效果明显:
-- 查看当前会话数
SELECT COUNT(*) FROM V$SESSION;
-- 调整最大连接数
ALTER SYSTEM SET MAX_SESSIONS = 500;
最后是I/O相关参数。这对SSD和HDD混合环境特别重要:
-- 调整异步I/O参数
ALTER SYSTEM SET DISK_ASYNCH_IO = TRUE;
-- 设置预读大小
ALTER SYSTEM SET DB_FILE_MULTIBLOCK_READ_COUNT = 32;
四、高级优化技巧
当基础优化都做完后,可以尝试这些进阶技巧:
第一个是分区表。DM的分区功能很强大,特别是时间序列数据:
-- 创建范围分区表示例
CREATE TABLE sales (
id NUMBER,
sale_date DATE,
amount NUMBER
) PARTITION BY RANGE (sale_date) (
PARTITION p2022 VALUES LESS THAN (TO_DATE('2023-01-01','YYYY-MM-DD')),
PARTITION p2023 VALUES LESS THAN (TO_DATE('2024-01-01','YYYY-MM-DD')),
PARTITION pmax VALUES LESS THAN (MAXVALUE)
);
-- 查询时自动分区裁剪
SELECT * FROM sales
WHERE sale_date BETWEEN TO_DATE('2023-06-01') AND TO_DATE('2023-06-30');
第二个是物化视图。适合报表类查询:
-- 创建物化视图
CREATE MATERIALIZED VIEW mv_sales_summary
REFRESH COMPLETE ON DEMAND
AS
SELECT product_id, SUM(amount) total_amount
FROM sales
GROUP BY product_id;
-- 查询物化视图
SELECT * FROM mv_sales_summary WHERE product_id = 1001;
第三个是SQL Profile。可以固定好的执行计划:
-- 创建SQL Profile
DECLARE
v_sql_text VARCHAR2(1000);
v_sql_id VARCHAR2(100);
BEGIN
v_sql_text := 'SELECT * FROM orders WHERE user_id = :1';
v_sql_id := DBMS_SQLTUNE.SQLTEXT_TO_SQLID(v_sql_text);
DBMS_SQLTUNE.IMPORT_SQL_PROFILE(
sql_text => v_sql_text,
profile => SQLPROF_ATTR('LEADING(@"SEL$1" "ORDERS"@"SEL$1")'),
name => 'PROFILE_ORDERS_BY_USER'
);
END;
/
五、日常维护的注意事项
优化不是一劳永逸的事,需要持续维护:
定期收集统计信息很重要:
-- 收集表统计信息
BEGIN
DBMS_STATS.GATHER_TABLE_STATS(
ownname => 'SCOTT',
tabname => 'ORDERS',
estimate_percent => 30,
cascade => TRUE
);
END;
/
-- 收集系统统计信息
BEGIN
DBMS_STATS.GATHER_SYSTEM_STATS('NOWORKLOAD');
END;
/
监控等待事件能发现潜在问题:
-- 查看TOP等待事件
SELECT event, total_waits, time_waited
FROM V$SYSTEM_EVENT
ORDER BY time_waited DESC;
定期检查锁情况也很重要:
-- 查看锁等待
SELECT
l.session_id,
s.username,
o.object_name,
l.locked_mode
FROM
V$LOCKED_OBJECT l,
DBA_OBJECTS o,
V$SESSION s
WHERE
l.object_id = o.object_id
AND l.session_id = s.sid;
六、总结与建议
经过这些年的实践,我发现DM数据库性能优化有几个关键点:
- 80%的性能问题来自SQL写法不当
- 合理的索引设计能解决大部分查询慢的问题
- 系统参数调优要根据实际负载来调整
- 高级功能如分区和物化视图要用在刀刃上
- 定期维护比一次性优化更重要
最后给个忠告:优化前一定要做好备份,有些参数改动可能会导致数据库不稳定。建议先在测试环境验证,确认没问题再上生产。
评论