c#基于servicestack.redis类库实现将oracle数据库数据同步到redis

本文讲述了作者如何通过优化Oracle数据库的分区技术,提升SQL查询效率,并利用多线程和DataTable转List技术,高效地将20万量级的数据每日分批插入Redis的过程。

一、整体思路:

1.我的测试数据总共为700多万,首先对数据按照日期分段进行划分查询,划分了五段(2021-06-01至2021-06-06、2021-06-07至2021-06-12等),作用是生成5个task,实现多线程。

2.为什么每次只查询一天得数据插入到redis呢?因为我得数据每天得量大约20万左右,如果查询多天数据数据量很大时进行插入,redis类库会直接报错。

3.在查询数据得时候,刚开始查询得特别慢,在sql语句优化下做了很多,比如创建索引,组合索引之类得,效果没什么起色。直到后来用到了分区技术,对oracle数据库表按照reporttime按天来进行分区,结果发现确实查询速度提升很高。

4.将datatable转list,将一天得list直接插入到redis,这块用到了自己封装得一个方法,将datatable转list()【 List<TRACEPOINT> datas = DataTableUtil.ToList<TRACEPOINT>(dt);】

5.在插入redis得方法上我也用过异步插入,但是效果跟同步没什么两样,就一直用了同步方法【redis.Set<List<TRACEPOINT>>("tracePoint" + DATE_STR, datas);】

二、关键代码:

 public class DataTableUtil
    {
        public static List<T> ToList<T>(DataTable dt)
        {
            var list = new List<T>();
            Type t = typeof(T);
            var plist = new List<PropertyInfo>(typeof(T).GetProperties());

            foreach (DataRow item in dt.Rows)
            {
                T s = System.Activator.CreateInstance<T>();
                for (int i = 0; i < dt.Columns.Count; i++)
                {
                    PropertyInfo info = plist.Find(p => p.Name == dt.Columns[i].ColumnName);
                    if (info != null)
                    {
                        if (!Convert.IsDBNull(item[i]))
                        {
                            info.SetValue(s, item[i], null);
                        }
                    }
                }
                list.Add(s);
            }
            return list;
        }
    }
 public class InsertRedisFromOra
    {
        public static  void insertData()
        {
           
            DateTime[] days = new DateTime[5] { DateTime.Parse("2021-06-01"), DateTime.Parse("2021-06-07"), DateTime.Parse("2021-06-13"), DateTime.Parse("2021-06-19"), DateTime.Parse("2021-06-25") };
            //对日期进行遍历
            foreach (DateTime day in days)
            {
                Task.Run(() =>
                {
                    for (DateTime cbt = day; cbt <= day.AddDays(5); cbt = cbt.AddDays(1))
                    {
                        //初始化redis客户端实例
                        RedisClient redis = new RedisClient("127.0.0.1", 6379, "123456");//redis服务IP和端口
                        string TRACEPOINTDATE = cbt.ToString("yyyy-MM-dd");
                        string DATE_STR = cbt.ToString("yyyyMMdd");
                        string sql = @"SELECT CAST(USER_ID AS NVARCHAR2(50)) USER_ID,LNG,LAT,TO_CHAR(REPORTTIME, 'yyyy-mm-dd hh24:mi:ss') REPORTTIME
                                    FROM LPB_TRACEPOINT_TEMP_TEST
                                    WHERE  REPORTTIME > TO_DATE(:TRACEPOINTDATE||' 00:00:00','YYYY-MM-DD hh24:mi:ss')
                         AND REPORTTIME< TO_DATE(:TRACEPOINTDATE||' 00:00:00','YYYY-MM-DD hh24:mi:ss')+1 
                   AND TYPE = 'GPS' AND LNG != 0 AND LAT != 0 ORDER BY REPORTTIME";
                        List<OracleParameter> ListOp = new List<OracleParameter>();
                        ListOp.Add(new OracleParameter("TRACEPOINTDATE", TRACEPOINTDATE));
                        //按天进行数据查询
                        DataTable dt = OracleHelper.Query(sql, ListOp.ToArray());
                        //将datatable转为list
                        List<TRACEPOINT> datas = DataTableUtil.ToList<TRACEPOINT>(dt);
                        //将数据插入到redis里面
                        redis.Set<List<TRACEPOINT>>("tracePoint" + DATE_STR, datas);
                        //插入后释放内存,否则内存耗费大性能降低
                        redis.Dispose();
                  }
                });
            }
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值