PS 读取数据库,条件选择有。时,用#代替

本篇博客详细介绍了使用 PowerShell 脚本从 Excel 文件中读取数据,并执行特定查询,将结果集进行处理并整合到哈希表中的过程。具体操作包括打开 Excel 文件连接,执行 SQL 查询筛选 MarginQty 大于 0 的记录,然后将查询结果中的 ContractNO 和 PartNumber 字段组合成键,MarginQty 字段的值作为值存储在哈希表中。

 cls;
$ExportRemainning="D:\ExportRemaining.xlsx"
$ExportRemainning_Hash=@{};


$ExcelConnection= New-Object -com "ADODB.Connection" 
$ExcelFile=$ExportRemainning
 
$ExcelConnection.Open("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=$ExcelFile;Extended Properties=Excel 12.0;")

$strQuery="Select * from [SPart Total Qty.$]  where [Margin Qty#] >0" 

$ExcelRecordSet=$ExcelConnection.Execute($strQuery)

do { 
    Write-Host "EXEC sp_InsertVendors '" $ExcelRecordSet.Fields.Item("Contract NO#").Value "'" 

    $Cont_PartNum=$ExcelRecordSet.Fields.Item("Contract NO#").Value +"#" + $ExcelRecordSet.Fields.Item("Part Number").Value;
    if ($ExportRemainning_Hash.Contains($Cont_PartNum))
    {
            $ExportRemainning_Hash.$Cont_PartNum =[int]$ExportRemainning_Hash.$Cont_PartNum + [int]$ExcelRecordSet.Fields.Item("Margin Qty#").Value;
    }
    else
    {
        $ExportRemainning_Hash.add($Cont_PartNum,$ExcelRecordSet.Fields.Item("Margin Qty#").Value)
    }

    $ExcelRecordSet.MoveNext()

Until ($ExcelRecordSet.EOF)

$ExcelConnection.Close()
    $end = Get-Date
    Write-Host -ForegroundColor Red ('Runtime: ' + ($end - $start).TotalSeconds)
    
    [System.GC]::Collect()

<think>好的,用户的问题是关于如何用Java通过多线程方式从MariaDB数据库中高效读取大量数据(比如1000万条)并加载到Ehcache的最佳实践。我需要结合多线程、数据库优化、缓存加载等方面来给出解决方案。 首先,用户的需求是高效读取大量数据,所以需要考虑数据库查询的优化。MariaDB是MySQL的分支,所以很多优化策略是相通的。比如分页查询,但传统的LIMIT offset, size在大量数据效率低下,尤其是offset很大。这里应该建议使用基于游标的分页,比如用自增主键或索引列来分批获取数据,这样每次查询都能利用索引,减少扫描间。参考了分页优化的方法,可能类似于引用中的分库分表或主从复制,但这里更直接的是查询优化。 接下来是多线程部分。如何分配任务给多个线程,每个线程处理不同的数据块。比如,可以将主键范围分成多个区间,每个线程处理一个区间,这样避免数据重复和锁竞争。线程池的使用也很重要,需要合理设置线程数量,避免过多导致数据库连接池耗尽或系统资源不足。线程间的协调和错误处理也需要考虑,比如某个线程失败后的重试机制。 然后是数据读取后的处理,比如转换、校验,再加载到Ehcache。Ehcache的加载方式需要注意线程安全,以及批量加载的效率。可能需要使用Ehcache的Bulk API,或者利用多线程并发put数据,但需要确保缓存的一致性。 此外,数据库连接池的配置也很关键。使用高性能的连接池如HikariCP,并正确配置最大连接数,避免连接泄漏。同,合理设置事务隔离级别,比如读已提交,或者使用MVCC(如引用2提到的InnoDB的MVCC),减少锁的争用,提高并发读取能力。 还有可能需要考虑的是JDBC的fetch size,适当调整每次从数据库读取的记录数,减少网络往返次数。以及结果集的流式读取,避免内存溢出,特别是处理1000万条数据,不能一次性加载到内存,而是分批次处理。 在代码结构方面,可能需要将任务分片,每个线程负责一个分片,使用CompletableFuture或ExecutorService来管理线程。同,监控每个线程的进度和性能,及调整参数。 最后,性能测试和调优是必不可少的环节。比如通过慢查询日志(引用3提到的定义慢查询间)来识别和优化查询,调整线程数量和分片策略,以达到最优的吞吐量。 总结下来,步骤可能包括:数据库查询优化(游标分页)、多线程任务分片、连接池配置、数据分批处理与缓存加载、错误处理与重试、性能监控与调优。需要将这些点有条理地组织起来,给出具体的实现方案和代码示例,同引用相关的知识点来支持建议的可行性。</think>针对Java多线程从MariaDB读取千万级数据并加载到Ehcache的高效实现方案,以下是分步骤解决方案: ### 一、数据库查询优化 1. **避免传统分页** 使用`WHERE id > ? LIMIT ?`代替`LIMIT offset, size`,利用自增主键实现游标分页,减少全表扫描: ```sql SELECT * FROM table WHERE id > {last_id} ORDER BY id LIMIT {batch_size} ``` 2. **索引优化** 确保查询字段(如主键)有覆盖索引,减少回表查询间[^2]。 3. **连接池配置** 使用HikariCP连接池,调整参数: ```java HikariConfig config = new HikariConfig(); config.setJdbcUrl("jdbc:mariadb://host/db"); config.setMaximumPoolSize(20); // 根据实际负载调整 ``` ### 二、多线程任务分配 1. **数据分片策略** 根据主键范围划分任务区间: ```java long minId = getMinIdFromDB(); long maxId = getMaxIdFromDB(); int threads = 8; long step = (maxId - minId) / threads; // 每个线程处理[startId, endId)区间 for (int i=0; i<threads; i++) { long start = minId + i*step; long end = (i == threads-1) ? maxId : start + step; executor.submit(new DataLoaderTask(start, end)); } ``` 2. **线程池配置** 使用固定大小线程池(根据CPU核心数和IO等待间调整): ```java ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 2); ``` ### 三、高效数据加载 1. **JDBC优化** - 设置`fetchSize(1000)`减少网络往返次数 - 开启自动提交关闭`conn.setAutoCommit(false)` ```java PreparedStatement ps = conn.prepareStatement(sql); ps.setFetchSize(1000); ResultSet rs = ps.executeQuery(); ``` 2. **Ehcache批量加载** 使用`putAll`方法减少锁竞争: ```java Cache<Integer, Entity> cache = ehcache.getCache(); Map<Integer, Entity> batchMap = new HashMap<>(1000); while (rs.next()) { Entity entity = convert(rs); batchMap.put(entity.getId(), entity); if (batchMap.size() >= 1000) { cache.putAll(batchMap); batchMap.clear(); } } ``` ### 四、容错与监控 1. **异常重试机制** 对数据库断连等异常添加重试逻辑: ```java int retry = 3; while (retry-- > 0) { try { // 执行查询 break; } catch (SQLException e) { if (retry == 0) throw e; Thread.sleep(1000); } } ``` 2. **进度监控** 使用原子计数器跟踪处理进度: ```java AtomicLong counter = new AtomicLong(0); executor.submit(() -> { long processed = counter.addAndGet(batchSize); if (processed % 100000 == 0) { System.out.println("已加载:" + processed); } }); ``` ### 五、性能调优建议 1. **调整JVM参数** 增加堆内存避免GC频繁: ``` -Xmx4g -Xms4g -XX:+UseG1GC ``` 2. **MariaDB服务端优化** 增加`innodb_buffer_pool_size`至物理内存的70%,开启`query_cache_type`[^1] 3. **网络优化** 确保应用服务器与数据库处于同一局域网,千兆以上网络带宽
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值