在没Hadoop 、GP 前提下怎么进行实时数据统计。

最近着手个项目,整体数据量有5亿多,每个月增量9000w。应用场景是Oltp 根据用户id直接计算各种维度值。

因为是Oltp 场景,直接根据用户id %2000分(方便后续横向扩展),有些喜欢扯分区表的或者顺序分表的请复习下数据库原理以及硬件原理。

分完表oltp 访问速度上了几个level。但是牵涉到一个实时统计的问题,需要对2000张表进行实时统计。因暂时没gp、hadoop 这种分布式数据库环境,以及怎么解决Oltp 到分布式数据库之间实时同步的问题。

想了个恶心的办法。对2000张表开启cdc 变更,记录时间段发生的变更userid,写了个多线程脚本实时根据这些userid 去更新数据。基本做到了实时统计,数据时间间隔差10分钟左右。

明年计划结构化数据先通过Gp计算,需要写个小程序来满足Cdc 变更到Gp的实时同步。

顺便附带 多线程统计脚本,还是powershell 写的。

#region hostinfo
$hostinfos=[System.Collections.ArrayList]@()
[void] $hostinfos.add(‘192.168.1.1‘)
[void] $hostinfos.add(‘1433‘)
[void] $hostinfos.add( $ClientSqlAccount)
[void] $hostinfos.add($ClientSqlPassWord)
[void] $hostinfos.add(‘db‘)
#endregion

#region 生成2000张表
$tables=[System.Collections.ArrayList]@()
<#
foreach($s in 0..1999)
{
    switch([void] $s)
    {
      {$s -lt 10 }{ [void] $tables.add(‘Tab‘+‘000‘+ $s.ToString());}
      {$s -ge 10 -and $s -lt 100 }{ [void] $tables.add((‘Tab‘+‘00‘+ $s.ToString()));  }
      {$s -ge 100 -and $s-lt 1000 }{ [void] $tables.add((‘Tab‘+‘0‘+ $s.ToString()));  }
      {$s -ge 1000  }{  [void] ($tables.add((‘Tab‘+ $s.ToString()))); }
    }

}
#>
#endregion

    $ClientSqlAccount=$hostinfos[2];
    $ClientSqlPassWord=$hostinfos[3];
    $ClientDB=$hostinfos[4];
    $log=‘d:‘
    $SqlServer=$hostinfos[0]  ;
    $Port=$hostinfos[1] ;
    $SqlString="Data Source="+$SqlServer+","+$Port+";uid="+$ClientSqlAccount+";Password="+$ClientSqlPassWord;
    $SqlConn = [System.Data.SqlClient.SqlConnection] $SqlString;
    $SqlConn.Open() ;
    $SqlConn.ChangeDatabase($ClientDB);
    $CC = $SqlConn.CreateCommand();
    $CC.CommandTimeout = 0;
    $CC.CommandText=‘select tabname  from Cdc_Change_userid where isdelete=0 group by tabname ‘
    $Reader = $CC.ExecuteReader();
    while ($Reader.read())
     {
        [void] $tables.add($Reader.GetString(0));
     }
    $SqlConn.Close();

#region Get SqlserverObjectScriptBlock
  $SBbillcellphone={
    param($hostinfos,$sqlcmd)
    Function Sqler_BillCellPhones
    {param(
         [array] $hostinfos
        ,[string] $sqlcmd
       )
        try
        {
               $ClientSqlAccount=$hostinfos[2];
               $ClientSqlPassWord=$hostinfos[3];
               $ClientDB=$hostinfos[4];
               $log=‘d:‘
               $SqlServer=$hostinfos[0]  ;
               $Port=$hostinfos[1] ;
               $SqlString="Data Source="+$SqlServer+","+$Port+";uid="+$ClientSqlAccount+";Password="+$ClientSqlPassWord;
               $SqlConn = [System.Data.SqlClient.SqlConnection] $SqlString;
               $SqlConn.Open() ;
               $SqlConn.ChangeDatabase($ClientDB);
               $CC = $SqlConn.CreateCommand();
               $CC.CommandTimeout = 0;
               $CC.CommandText=$sqlcmd
               $CC.ExecuteScalar();
               $SqlConn.Close();
        }
        catch
        {

           $day=(Get-Date -Format "yyyyMMdd").tostring();
           $return=‘Error‘;
           ( ‘Sqler_BillCellPhones  : ‘+((Get-Date).tostring())+‘ ‘+ $SqlServer+‘,‘+$Port +‘ ‘+$_.Exception.Message )|Out-File  -FilePath  "$log\tab_$day.log"   -Append -Force

        }
    }
    Sqler_BillCellPhones $hostinfos $sqlcmd
 }

    $throttleLimit=5
    $sqlcmd=‘exec csp_billcellphone_Score ‘‘@tabname‘‘‘;
    $SessionState = [system.management.automation.runspaces.initialsessionstate]::CreateDefault()
    $Pool = [runspacefactory]::CreateRunspacePool(1, $throttleLimit, $SessionState, $Host)
    $Pool.Open()
    $threads = @()
    $handles = foreach($table in $tables) {
        $sqlcmd=‘exec csp_billcellphone_Score ‘‘@tabname‘‘‘;
        $sqlcmd=$sqlcmd-replace ‘@tabname‘,$table
        $powershell = [powershell]::Create().AddScript($SBbillcellphone).AddArgument($hostinfos).AddArgument($sqlcmd)
        $powershell.RunspacePool = $Pool
        $powershell.BeginInvoke()
      $threads += $powershell
    }
    do {
      $i = 0
      $done = $true
      foreach ($handle in $handles) {
        if ($handle -ne $null) {
          if ($handle.IsCompleted) {
            $threads[$i].EndInvoke($handle)
            $threads[$i].Dispose()
            $handles[$i] = $null
          } else {
            $done = $false
          }
        }
        $i++
      }
      if (-not $done) { Start-Sleep -second 1 }
    } until ($done)
 Remove-Variable -Name handles, threads,powershell;
 [System.GC]::Collect(); [System.GC]::WaitForPendingFinalizers()
时间: 2024-11-02 21:33:16

在没Hadoop 、GP 前提下怎么进行实时数据统计。的相关文章

【执行力决定命】第4集《有价值的额外贡献,要建立在做好本职前提下》

「音频原文」http://dwz.cn/6sAOCC 大家好,我是林琳笨,今天一起分享<有价值的额外贡献,要建立在做好本职前提下> 先引用一个华为内部的故事: 华为有个新员工,入职没几天,做了几十页的发展战略书,打算交给任正非任总,他想就算做的不好,任总也能鼓励我一下,没想到任总直接把方案扔垃圾桶,批评说:不要想着做惊且动地变革,先从小事做起,老实把自己任务完成. 记得前几年,安排一位同事做我临时助理陪我去深圳出差,事前说好他主要负责5个深圳合作方确定约见时间.地点.记录和后续跟进.当天晚上抵

hadoop伪分布下的sqoop基本安装配置

1.环境工具版本介绍 centos6.4(Final) jdk-7u60-linux-i586.gz hadoop-1.1.2.tar.gz sqoop-1.4.3.bin__hadoop-1.0.0.tar.gz mysql-5.6.11.tar.gz 2.安装centos 参照网上Ultra的使用制作了U盘启动,直接格式化安装系统,具体做法网上资料很多,但注意最好不要在安装时改主机名称,也最好不要利用图形化界面添加用户,因为我出过问题重做了系统,这些terminal中都能完成的 3.安装jd

不修改模板的前提下修改VisualState中的某些值

UWP里有一件非常令人不爽的事,大部分控件只提供了Normal状态下的Background,Foreground,BorderBrush,而控件一般至少具有Normal.PointerOver.Pressed.Disabled,ItemContainerStyle还有Selected.PointerOverSelected.PressedSelected这几种.那么常规方法怎么修改这几个状态内的值呢? 当然是贴一遍又臭又长的Style. 那如果有很多不是很一样的控件,除了修改模板或者自定义一个控

非安全传输协议前提下,Open API安全协议设计

本文考虑:在不使用安全传输协议的前提下,Open API调用的安全问题. 角色定义 处理流程 调用方消息发送流程 发布者消息接收流程 调用结果返回流程 代码设计 调用方代码设计 发布者代码设计 作者:刘海龙 微博:[http://weibo.com/liuhailong2008] 博客:[http://blog.csdn.net/stationxp] 角色定义 发布者:Open API的发布者. 调用方:Open API的调用者. 处理流程 调用方消息发送流程 生成一个UUID,称为_seed.

Unity3d热更新全书-加载(二)如何在不用AssetBundle的前提下动态加载预设

Unity3D的主要构成大家都知道,首先是场景图,场景图上的节点构成一颗树. 每个节点对应一个GameObject对象 然后每个GameObject有若干个组件 有一些组件会与资源产生关系,比如MeshRenderer会关联材质,材质会关联shader和贴图 场景图的一部分可以被保存为一个预设,prefab. 有时候我们会需要用预设去复用,而预设的加载似乎只能通过AB去打包,其实不然,这里我们有一个开源的库就可以解决这个问题. 为什么不使用AB,可以见上一篇,加载(一),不使用AB一份资源全平台

自问自答-hadoop在安全模式下究竟干了什么见不得人的事

本来想自己从网上搜集整理的,但是发现吴超写的刚刚好,不多不少,所以直接转载(图片失效了,用自己的图片) http://www.superwu.cn/2013/08/23/548/ 在hadoop集群的时候,集群的运行会进入到安全模式(safeMode)下.在安全模式下运行一段时间后,自动退出. 那么,系统在安全模式下干什么了? 当集群启动的时候,会首先进入到安全模式.系统在安全模式下,会检查数据块的完整性.假设我们设置的副本数(即参数dfs.replication)是5,那么在dataNode上

ACdream 1135(MST-最小生成树边上2个值,维护第一个最小的前提下让另一个最小)

F - MST Time Limit: 2000/1000MS (Java/Others) Memory Limit: 128000/64000KB (Java/Others) SubmitStatus Problem Description Given a connected, undirected graph, a spanning tree of that graph is a subgraph that is a tree and connects all the vertices to

比较次数最小的前提下,求数列的最大和最小值(Java实现)

1 /** 2 * 在一组数字当中,在尽可能小的比较此处的前提下,获取最大值和最小值 3 * @author JimmyPC 4 * 5 */ 6 public class Problem_MinMax { 7 8 public class Node { 9 public int min; 10 public int max; 11 } 12 //获取最大最小值 13 public Node getMinMax(int a[],int n){ 14 Node minmax = new Node(

相同更改数据量的前提下,单次COMMIT和多次COMMIT对日志空间浪费的影响对比

LGWR进程按照顺序写在线日志,中间不会跳跃,而且LGWR进程不会在同一个日志快写2次,即使一次写入的日志快只占几个字节,下次不会再用了,这就造成日志空间的浪费.Oracle做一次Commit,就会触发LGWR进程进行日志缓冲到日志文件的写入操作,因此可以说更改相同数据量的前提下,如果提交过于频繁,产生的日志可能就会越多,即使第一次Commit占用的日志块仍可以存储下一次需要写入的日志缓冲,那么下一次Commit会再次占用一个新的日志块. 实验: 1.系统的日志块大小是512字节. SQL> s