/*+APPEND*/插入性能总结

使用append提示进行insert叫做直接路径加载插入。

【特点】

1使用这种提示因为系统不去查找freelist链表中的空闲块,直接在高水标记位以上插入数据,因此速度比较快。但若是对于经常delete的表,浪费磁盘空间太大!

2它不记录日志,因此一旦插入的数据在没有保存回磁盘的时候发生掉电之类的状况插入的数据不能重做。

3/*+append*/后,需要马上提交,否则会影响下一次修改失败(insert,update,delete)

在Oracle Database 10g Enterprise Edition Release 10.2.0.1.0中,如果插入操作的语法是

insert /*+append*/ into XXX values(XXX);

那么系统加的是row exclusive锁,也就是正常insert所加的行级锁,但是如果插入操作的语法是

insert /*+append*/ into XXX select XXX from XXX;

那么系统加的是exclusive锁,相当于表级锁,加表级锁意味着在本会话没有commit的时候其他任何会话都不能再进行insert,update,delete操作

【相关SQL语句】

检查数据库归档模式(NOARCHIVELOGARCHIVELOG):

Archive log list

或者

SELECT log_mode from v$database;

查看当前redo日志大小:

select name,value,class from v$sysstat where name='redo size';

或者打开统计,这个更准确地统计当前语句生成的redo,推荐使用

set autotrace traceonly statistics

普通插入方式:

insert into t select * from dba_objects;

append插入方式:

insert /*+append*/ into t select * from dba_objects;

Append+nologing插入方式:

insert /*+append*/ into t nologging select * from dba_objects;

【测试结论】

1、无论归档模式、还是非归档模式,append+nologing插入方式效果最好,生成最小的redo日志

2、非归档模式下,append插入模式效果不错

3、归档模式下,append插入模式没有效果

【测试例子】

http://wenku.baidu.com/view/2cd6472a4b73f242336c5fa8.html

【我的测试】

从以下对比可以看出,增加hint方法,速度增加4

还真的有这么神,都是180万行的表拷贝,我的测试如下:

insert into p_nbsc_ho1 select * from p_nbsc_ho (消耗时间73分钟)

insert /*+append*/ into p_nbsc_ho2 select * from p_nbsc_ho (消耗时间7分钟)

弊端:

insert /*+append*/ 如果不commit的话,会对该表加6级锁,也就是说,即使此时select 这个表都会报错。

因此append提示的语句首先不能是业务表,其次要尽快提交commit,所以一般情况不敢用hint了。

 

原博文地址:http://blog.itpub.net/26838108/viewspace-721266/

上述的优化方案看起来可行,但是还存在欠缺,因为代码的不全面,下面我进行补充public static String parseToSQLCondition(String matchMethod) { // 去除字符串两端的空格 matchMethod = matchMethod.trim(); // 根据字符串中是否包含 "or" 来决定使用 "or" 还是 "and" 作为分隔符 String[] conditions = matchMethod.split(matchMethod.indexOf("or") >= 0 ? " or " : " and "); // 用于存储最终的 SQL 条件 StringBuilder sqlCondition = new StringBuilder(); // 遍历每个条件 for (int i = 0; i < conditions.length; i++) { String condition = conditions[i].trim(); // 分割条件,得到字段名、匹配方法和匹配值 String[] parts = condition.split(" "); if (parts.length < 3) { throw new IllegalArgumentException("Invalid condition format: " + condition); } String field = parts[0]; // 字段名 String matchType = parts[1]; // 匹配方法 String values = parts[2]; // 匹配值 // 根据匹配类型生成相应的 SQL 条件 if (ConstantInterface.WARNING_CONDITION_KEYWORD_LIKE.equals(matchType)) { // 如果匹配类型是 "包含",则将匹配值按逗号分割,生成多个 "like" 条件 String[] valueList = values.split(","); sqlCondition.append("( "); // 添加左括号,用于将多个 "like" 条件括起来 for (int j = 0; j < valueList.length; j++) { if (j > 0) { sqlCondition.append(" or "); // 如果不是第一个条件,添加 "or" } sqlCondition.append(field).append(" like '%").append(valueList[j]).append("%'"); // 生成 "like" 条件 } sqlCondition.append(" ) "); // 添加右括号 } else if (ConstantInterface.WARNING_CONDITION_KEYWORD_NOTLIKE.equals(matchType)) { // 如果匹配类型是 "不包含",则生成 "not like" 条件 sqlCondition.append(field).append(" not like '%").append(values).append("%'"); } else { // 如果匹配类型不是 "包含" 或 "不包含",则抛出异常 throw new IllegalArgumentException("Unsupported match type: " + matchType); } // 如果不是最后一个条件,添加 "or" 或 "and" if (i < conditions.length - 1) { sqlCondition.append(matchMethod.indexOf("or") >= 0 ? " or " : " and "); } } // 返回生成的 SQL 条件,添加外层的括号 return sqlCondition.toString(); } private void conditionsMeetsDataForRulesToCCMNuwa(LocalDateTime statrtDate, LocalDateTime endDate, Integer csdcConditionSize, GeWarningRulesListEntity rules) { /** 调用 抽取方法 获取数据返回 若是无数据 默认 null*/ List<ConditionsMeetsEntity> conditionsMeetsEntities = getConditionsMeetsList(statrtDate, endDate, csdcConditionSize, rules); if (CollectionUtils.isEmpty(conditionsMeetsEntities)) { return; } System.out.println(">>>>>>>>>>>>>>>>>Into ge_rules_meets_data statrtDate:" + statrtDate); System.out.println(">>>>>>>>>>>>>>>>>Into ge_rules_meets_data endDate:" + endDate); System.out.println(">>>>>>>>>>>>>>>>>Into ge_rules_meets_data csdcConditionSize:" + csdcConditionSize); System.out.println(">>>>>>>>>>>>>>>>>Into ge_rules_meets_data rulesID:" + rules.getId()); System.out.println(">>>>>>>>>>>>>>>>>Into ge_rules_meets_data:" + JSON.toJSONString(conditionsMeetsEntities)); /** 遍历全部systemid */ for (ConditionsMeetsEntity conditionsMeetsEntity : conditionsMeetsEntities) { /** 提权 systemid 和时间戳 当做条件查询符合的数据*/ List<CCMDataEntity> ccmDataEntities = ccmDataEntityMapper.selectCCMDataEntityList( CCMDataEntity.builder().systemId(conditionsMeetsEntity.getSystemId()).timestamp(conditionsMeetsEntity.getMatchTime()).build()); if (CollectionUtils.isEmpty(ccmDataEntities)) { break; } /** 当出现通一时间节点存在多条数据的时候 默认获取第一条 */ CCMDataEntity ccmDataEntity = ccmDataEntities.get(0); CsdcRulesMeetsDataEntity rulesMeetsData = new CsdcRulesMeetsDataEntity(); /*** SystemId*/ rulesMeetsData.setSystemId(ccmDataEntity.getSystemId()); /*** 通道名称*/ rulesMeetsData.setChannelName(ccmDataEntity.getChannelName()); /*** Modality*/ rulesMeetsData.setModality(ccmDataEntity.getModality()); /*** 产品*/ rulesMeetsData.setProduct(ccmDataEntity.getProduct()); /*** 医院名称*/ rulesMeetsData.setHospitalName(ccmDataEntity.getHospitalName()); /** * 区域:原zone */ rulesMeetsData.setRegion(ccmDataEntity.getZone()); /** * 告警类型 */ rulesMeetsData.setWarningType(ccmDataEntity.getChannelName()); /** * 告警时间 */ rulesMeetsData.setWarningTime(ccmDataEntity.getTimestamp()); /** * 实际值 */ rulesMeetsData.setNowValue(ccmDataEntity.getValue()); /** * 根据warning_time开始算起的持续时间 */ // rulesMeetsData.setContinuedWarningTime(ccmDataEntity.getValue()); /** * 数据来源:告警信息详情 */ // rulesMeetsData.setAlertDetails(ccmDataEntity.getValue()); /** * 间隔时间 */ // rulesMeetsData.setWarningFrequnce(rules.get); /** * 数据来源 CCM or EE or APM */ rulesMeetsData.setDataSourceName(ccmDataEntity.getDataSource()); /** * 这个字段应该是APM单独有的字段,原:channelNo */ // rulesMeetsData.setEventId(ccmDataEntity.getDataSource()); /** * 规则名称 */ rulesMeetsData.setRulesName(rules.getName()); /** * 规则id */ rulesMeetsData.setRulesId(rules.getId()); /** * 推送类型:里面包含1-短信,2-邮件,3-工单,4-APM */ rulesMeetsData.setPushType(rules.getNotificationMethod()); /** * 推送状态:0:未推送,1:已推送 */ // rulesMeetsData.setPushStatus(ccmDataEntity.getDataSource()); /** * 消息内容 */ // rulesMeetsData.setActualValue(ccmDataEntity.getDataSource()); /** * 推送时间 */ // rulesMeetsData.setPushTime(ccmDataEntity.getDataSource()); /** * 第一条持续数据的id */ // rulesMeetsData.setFirstContinueDataId(ccmDataEntity.getDataSource()); /** * 数据状态,条件更新时禁用对应规则的推送数据,0-禁用,其他可用 */ rulesMeetsData.setDataStatus("1"); /** 当规则符合时 添加数据到新表中 */ System.out.println(">>>>>>>>>>>>>>>>>Into ge_rules_meets_data DataDataData:" + JSON.toJSONString(rulesMeetsData)); csdcRulesMeetsDataEntityMapper.insertCsdcRulesMeetsDataEntity(rulesMeetsData); /** 创建 修改条件 */ ConditionsMeetsEntity conditionsMeets = ConditionsMeetsEntity.builder().ruleId(rules.getId()) .systemId(ccmDataEntity.getSystemId()).isConsumed(1).build(); /** 修改满足规则数据 记录数据为已消耗数据*/ conditionsMeetsEntityMapper.updateConditionsMeetsConsumed(conditionsMeets); } }
最新发布
12-04
public void ruleDeterminationForNuwaOrCCM() { log.info("[RULE-DETERMINATION-CCM/NVWA] 开始对CCM/NVWA进行规则判定"); /** 获取当前时间 */ String nowTime = DateUtils.getTime(); log.info("[RULE-DETERMINATION-CCM/NVWA] 获取当前时间:{}", nowTime); /**创建实例用于查询状态为启用状态的给规则*/ GeWarningRulesListEntity geWarningRulesListEntity = new GeWarningRulesListEntity(); geWarningRulesListEntity.setStatus(ConstantInterface.WARNING_RULES_TRUE); geWarningRulesListEntity.setRulesType(ConstantInterface.WARNING_RULES_NUWACCM_TYPE); log.info("[RULE-DETERMINATION-CCM/NVWA] 创建规则查询实例:状态={},规则类型={}", ConstantInterface.WARNING_RULES_TRUE, ConstantInterface.WARNING_RULES_NUWACCM_TYPE); // 获取可用规则集合 List<GeWarningRulesListEntity> geWarningRulesListEntityList = getRulesByTypeAndIds(DataSourceEnum.NUWA_CCM.getValue()); log.info("[RULE-DETERMINATION-CCM/NVWA] 获取 {} 条规则,类型:{}", geWarningRulesListEntityList != null ? geWarningRulesListEntityList.size() : 0, DataSourceEnum.NUWA_CCM.getValue()); // 如果没有可用的规则信息,直接结束方法 if (CollectionUtils.isEmpty(geWarningRulesListEntityList)) { log.info("[RULE-DETERMINATION-CCM/NVWA] 未找到规则,退出方法"); return; } /** 遍历规则中的条件 筛选出符合条件的数据 若存在 则记录数据到 数据表③ */ /** 组装条件 查询表①符合条件的数据 */ geWarningRulesListEntityList.stream() .filter(rules -> !CollectionUtils.isEmpty(rules.getCsdcCondition())) /** 判定当前规则是否处于开启状态*/ .filter(rules -> ConstantInterface.WARNING_RULES_TRUE.equals(rules.getStatus())) .forEach(rules -> { log.info("[RULE-DETERMINATION-CCM/NVWA] 处理规则ID:{},规则名称:{}", rules.getId(), rules.getName()); StringBuffer stringBuffer = new StringBuffer(" 1=1 "); /** 获取规则配置的systemid */ String systemId = rules.getSystemId(); /** 获取规则配置的systemid 在保状态 */ String insuranceType = rules.getInsuranceType(); /** 获取规则配置的modality */ String modality = rules.getModality(); /** 获取规则配置的product */ String product = rules.getProduct(); /** 获取规则配置的hospitalName */ String hospitalName = rules.getHospitalName(); log.info("[RULE-DETERMINATION-CCM/NVWA] 规则ID {} 的条件:systemId={},insuranceType={},modality={},product={},hospitalName={}", rules.getId(), StringUtils.defaultIfBlank(systemId, "null"), StringUtils.defaultIfBlank(insuranceType, "null"), StringUtils.defaultIfBlank(modality, "null"), StringUtils.defaultIfBlank(product, "null"), StringUtils.defaultIfBlank(hospitalName, "null")); /** 如果规则的systemId属于无效参数,说明要求数据全匹配,直接返回true*/ if (StringUtils.isNotBlank(systemId)) { stringBuffer.append("and system_id= '" + systemId + "' "); } /** 如果规则的systemId属于无效参数,说明要求数据全匹配,直接返回true*/ if (StringUtils.isNotBlank(insuranceType)) { switch (insuranceType) { case ConstantInterface.WARNING_RULES_SYSTEM_ASSET_STATUS_TRUE: stringBuffer.append("and asset_status in ( '" + ConstantInterface.WARNING_RULES_SYSTEM_ASSET_STATUS_TRUE_IW + "' , '" + ConstantInterface.WARNING_RULES_SYSTEM_ASSET_STATUS_TRUE_IC + "') "); break; case ConstantInterface.WARNING_RULES_SYSTEM_ASSET_STATUS_ALL: /** 默认显示为ALL 则不加筛选条件 */ break; case ConstantInterface.WARNING_RULES_SYSTEM_ASSET_STATUS_FALSE: stringBuffer.append("and asset_status in ( '" + ConstantInterface.WARNING_RULES_SYSTEM_ASSET_STATUS_FALSE_OC + "' , '" + ConstantInterface.WARNING_RULES_SYSTEM_ASSET_STATUS_FALSE_OW + "') "); break; } } /** 如果规则的modality属于无效参数,说明要求数据全匹配,直接返回true*/ if (StringUtils.isNotBlank(modality)) { stringBuffer.append("and modality= '" + modality + "' "); } /** 如果规则的product属于无效参数,说明要求数据全匹配,直接返回true*/ if (StringUtils.isNotBlank(product)) { stringBuffer.append("and product= '" + product + "' "); } /** 如果规则的hospitalName属于无效参数,说明要求数据全匹配,直接返回true*/ if (StringUtils.isNotBlank(hospitalName)) { stringBuffer.append("and hospital_name= '" + hospitalName + "' "); } log.info("[RULE-DETERMINATION-CCM/NVWA] 为规则ID {} 构建基础SQL条件:{}", rules.getId(), stringBuffer.toString()); /** 获取当前规则中的所有条件数据 */ List<CsdcConditionTableEntity> csdcCondition = rules.getCsdcCondition(); for (int index = csdcCondition.size() - 1; index >= 0; index--) { StringBuffer sqlNew = new StringBuffer(stringBuffer); CsdcConditionTableEntity condition = csdcCondition.get(index); /** 匹配数据源 Nuwa/CCM */ if (StringUtils.isNotBlank(condition.getDataSource())) { sqlNew.append("and data_source= '" + condition.getDataSource() + "' "); } /** 匹配 channel字段名称 */ String conditionField = condition.getConditionField(); if (StringUtils.isNotBlank(conditionField)) { sqlNew.append("and channel_name= '" + condition.getConditionField() + "' "); } /** 判定当前条件是 关键字还是上下限 */ Integer conditionType = condition.getConditionType(); /** 获取条件参数 */ String matchMethod = condition.getMatchMethod(); /** 格局不同情况进行 条件的整理判定 */ if (conditionType != null) { sqlNew.append("and ( "); switch (conditionType) { case ConstantInterface.WARNING_CONDITION_NUMBER_TYPE: /** 数字匹配上下限 获取以保存的关系表达式 */ String value = matchMethod.replace(conditionField, "`value` "); sqlNew.append(value); break; case ConstantInterface.WARNING_CONDITION_KEYWORD_TYPE: /** 温度 包含 开,合 or 温度 不包含 关 */ String sqlCondition = parseToSQLCondition(matchMethod.replace(conditionField, "`value`")); sqlNew.append(sqlCondition); break; case ConstantInterface.WARNING_CONDITION_ALGORITHM_TYPE: /** 算法类型数值计算匹配 todo */ // String sqlCondition = parseToSQLCondition(matchMethod.replace(conditionField, "`value`")); // sqlNew.append(sqlCondition); break; } sqlNew.append(" ) "); } /** 连续 or 单次 */ Integer executionType = condition.getExecutionType(); /** 若果是连续 则去 时间区间/10 获取次数条件 反之 根据字段threshold_count 来判定 */ Long thresholdTime = condition.getThresholdTime(); if (thresholdTime != null) { /** 转换当前时间 为截止时间 */ LocalDateTime endDate = LocalDateTime.parse(nowTime, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); /** 通过计算 获取起始时间 */ LocalDateTime statrtDate = endDate.minus(thresholdTime, ChronoUnit.MINUTES); sqlNew.append(" AND STR_TO_DATE(timestamp, '%Y-%m-%dT%H:%i:%s') "); sqlNew.append(" BETWEEN '" + statrtDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss")) + "' AND '" + endDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss")) + "' "); log.info("[RULE-DETERMINATION-CCM/NVWA] 为条件ID {} 添加时间范围:开始时间:{},结束时间:{}", condition.getConditionId(), statrtDate, endDate); } Long thresholdCount = condition.getThresholdCount(); /** 判定 连续或者单次时 数据出现的次数 */ if (executionType != null && executionType == ConstantInterface.WARNING_CONDITION_EXECUTION_CONTINUOUS && thresholdTime != null) { thresholdCount = thresholdTime / ConstantInterface.WARNING_CONDITION_EXECUTION_TASK; } sqlNew.append(" GROUP BY system_id HAVING COUNT(*) >= " + thresholdCount); log.info("[RULE-DETERMINATION-CCM/NVWA] 处理条件索引:{},条件ID:{},规则ID:{},匹配方法:{},条件参数:{},执行类型:{},阈值计数:{},最终SQL:{}", index, condition.getConditionId(), rules.getId(),conditionType, matchMethod, executionType, thresholdCount,sqlNew.toString()); /** todo 待定 ing */ List<CCMDataEntity> dataEntities = ccmDataEntityMapper.selectNuwaCCMDataListByRule(sqlNew.toString()); log.info("[RULE-DETERMINATION-CCM/NVWA] 为规则ID:{},条件ID:{} 获取 {} 条CCMDataEntity记录", dataEntities != null ? dataEntities.size() : 0, rules.getId(), condition.getConditionId()); if (!CollectionUtils.isEmpty(dataEntities)) { /** 创建一个集合 记录本次符合条件的数据 */ List<ConditionsMeetsEntity> ruleConditionsMeetsEntities = new ArrayList<ConditionsMeetsEntity>(); /** 数据满足的条件的规则id */ String rulesId = rules.getId(); /** 数据满足的条件id */ Long conditionId = condition.getConditionId(); log.info("[RULE-DETERMINATION-CCM/NVWA] 准备为规则ID:{},条件ID:{} 存储 {} 条匹配记录", dataEntities.size(), rulesId, conditionId); /** ********* */ for (CCMDataEntity dataEntity : dataEntities) { /** 当前数据systemid */ String systemId1 = dataEntity.getSystemId(); /** 当前数据 TS时间 */ String timestamp = dataEntity.getTimestamp(); /** 初始化需要存储的数据 */ ConditionsMeetsEntity ruleConditionsMeets = ConditionsMeetsEntity.builder() .systemId(systemId1) .conditionId(conditionId.toString()) .ruleId(rulesId) .matchTime(timestamp).build(); ruleConditionsMeetsEntities.add(ruleConditionsMeets); log.info("[RULE-DETERMINATION-CCM/NVWA] 添加ConditionsMeetsEntity:systemId={},ruleId={},conditionId={},matchTime={}", systemId1, rulesId, conditionId, timestamp); } /** 存储符合条件的数据 */ try { conditionsMeetsEntityMapper.insertConditionsMeetsEntityForList(ruleConditionsMeetsEntities); log.info("[RULE-DETERMINATION-CCM/NVWA] 为规则ID:{},条件ID:{} 插入 {} 条ConditionsMeetsEntity记录", ruleConditionsMeetsEntities.size(), rulesId, conditionId); } catch (Exception e) { log.error("[RULE-DETERMINATION-CCM/NVWA] Failed to insert ConditionsMeetsEntity for rule ID: {}, conditionId: {}, error: {}", rulesId, conditionId, e.getMessage(), e); throw e; } } } /** 当条件判定直线完 需要进行 匹配符合条件间隔的数据 */ /** 定义一个秒 用来计算 */ Long seconds = 0L; /** 条件间隔时间-小时 */ // String parameterIntervalHours = rules.getParameterIntervalHours(); // if (StringUtils.isNoneBlank(parameterIntervalHours)) { // seconds += Long.valueOf(parameterIntervalHours) * 60 * 60; // } /** * 条件间隔时间-分钟 */ String parameterIntervalMinutes = rules.getParameterIntervalMinutes(); if (StringUtils.isNoneBlank(parameterIntervalMinutes)) { seconds += Long.valueOf(parameterIntervalMinutes) * 60; } /** * 条件间隔时间-秒 */ // String parameterIntervalSeconds = rules.getParameterIntervalSeconds(); // if (StringUtils.isNoneBlank(parameterIntervalSeconds)) { // seconds += Long.valueOf(parameterIntervalSeconds); // } log.info("[RULE-DETERMINATION-CCM/NVWA] 为规则ID:{} 计算间隔时间:{} 秒", rules.getId(), seconds); /** 转换当前时间 为截止时间 */ LocalDateTime endDate = LocalDateTime.parse(nowTime, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); /** 通过计算 获取起始时间 */ LocalDateTime statrtDate = endDate.minus(seconds, ChronoUnit.SECONDS); log.info("[RULE-DETERMINATION-CCM/NVWA] 规则ID {} 的时间范围:开始时间:{},结束时间:{}", rules.getId(), statrtDate, endDate); /** 当 当前规则中 满足条件的数据都存储到 满足条件数据表中时 进行 规则维度 数据判定*/ conditionsMeetsDataForRulesToCCMNuwa(statrtDate, endDate, csdcCondition.size(), rules); log.info("[RULE-DETERMINATION-CCM/NVWA] 为规则ID:{} 执行conditionsMeetsDataForRulesToCCMNuwa", rules.getId()); }); /** 当规则数据都判定之后 进行 对符合规则的数据匹配去重原则 */ operationsRulesMeetsData(geWarningRulesListEntityList, nowTime); log.info("[RULE-DETERMINATION-CCM/NVWA] 执行operationsRulesMeetsData,规则数量:{}", geWarningRulesListEntityList.size()); log.info("[RULE-DETERMINATION-CCM/NVWA] CCM/NVWA规则判定完成"); } 解析代码 分析业务逻辑
12-04
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值