项目是用oralce 10g + tomcat +jsp的
  其中,有订单流水号,如年月日+7位流水号。以前做的东西里边因为订单少,就每次都去数据库取一次最后的订单号,再来生成新的订单好。但是现在这个项目里,每天的订单可能10W左右,而且下单时间比较集中。那该去怎么处理这个订单流水号?
  还有就是,要对用户的所有操作,主要是查看/购买商品,点击/购买广告产品的记录。做这种操作轨迹记录,该怎么设计表,以及如何做查询优化,现在已有20W用户操作  麻烦路过的大哥大姐帮帮忙,指点下小弟先谢谢了

解决方案 »

  1.   

    增加一个每日流水号的表,字段两个,一个是日期,一个是流水号(数值),先插入两年的记录,流水号都初始化为1。
    每次需要新的流水号时,就用当前的日期去获取当天的流水号再补充0到7位,用了一个就把该表的流水号+1,相当于建立了一个动态的sequence。
      

  2.   

    我们的订单号就的用SEQUENCE的,不过经常订单号会断掉,呵呵,因为SEQUENCE用完就没有了,后面用触发器自动去生成就好了,
      

  3.   

    用SEQUENCE吧  把SEQUENCE常驻在cache中  就不会丢失
    第二个 应该是需要前台操作才能统计的吧  估计会要设计表格插入数据统计
    20w每天产生100-200w数据很正常啊那就
    你最终目的应该是要统计每个商品的 点击量  销售量吧
    那就每天统计好 点击量  销售量  然后清掉 数据记录表
    个人意见 一起学习
      

  4.   

    ---------------- 若订单流水号是字符串型的话:(Oracle 10g)  -----------------
    CREATE SEQUENCE order_id_seq INCREMENT BY 1 START WITH 1 MAXVALUE 9999999 CYCLE CACHE 10;SET SERVEROUTPUT ON
    DECLARE
      order_id VARCHAR(17); -- 订单流水号
    BEGIN
      SELECT to_char(SYSDATE,'YYYYMMDD')||LPAD( to_char(order_id_seq.nextval),7,'0') INTO order_id FROM dual;
      DBMS_OUTPUT.PUT_LINE('当前流水号是:'||order_id);
    END;
    /---------------- 若订单流水号是数值型的话:(Oracle 10g)  -----------------
    CREATE SEQUENCE order_id_seq INCREMENT BY 1 START WITH 1 MAXVALUE 9999999 CYCLE CACHE 10;SET SERVEROUTPUT ON
    DECLARE
      order_id NUMBER(18,0); -- 订单流水号
    BEGIN
      SELECT to_number(to_char(SYSDATE,'YYYYMMDD')||LPAD( to_char(order_id_seq.nextval),7,'0')) INTO order_id FROM dual;
      DBMS_OUTPUT.PUT_LINE('当前流水号是:'||order_id);
    END;
    /
    ---------------- 若订单流水号是字符串型的话:(Oracle 11g)  -----------------
    CREATE SEQUENCE order_id_seq INCREMENT BY 1 START WITH 1 MAXVALUE 9999999 CYCLE CACHE 10;SET SERVEROUTPUT ON
    DECLARE
      order_id VARCHAR(17); -- 订单流水号
    BEGIN
      order_id := to_char(SYSDATE,'YYYYMMDD')||LPAD( to_char(order_id_seq.nextval),7,'0');
      DBMS_OUTPUT.PUT_LINE('当前流水号是:'||order_id);
    END;
    /---------------- 若订单流水号是数值型的话:(Oracle 11g)  -----------------
    CREATE SEQUENCE order_id_seq INCREMENT BY 1 START WITH 1 MAXVALUE 9999999 CYCLE CACHE 10;SET SERVEROUTPUT ON
    DECLARE
      order_id NUMBER(18,0); -- 订单流水号
    BEGIN
      order_id := to_number(to_char(SYSDATE,'YYYYMMDD')||LPAD( to_char(order_id_seq.nextval),7,'0'));
      DBMS_OUTPUT.PUT_LINE('当前流水号是:'||order_id);
    END;
    /
      

  5.   

    使用for update强制串行,每天从1开始,生成唯一流水号
    每天10W,性能没问题
    --创建流水号表
    create table T_SERIALNO
    (
      CURDAT     VARCHAR2(10) not null,
      SERIALNUM  NUMBER(8) not null
    );--创建函数
    CREATE OR REPLACE FUNCTION GetSerialNo RETURN VARCHAR2 IS
      v_DateStr   VARCHAR2(10); --系统日期对应的字符串
      v_SerialNum NUMBER(7); --流水序号
    BEGIN
      --取系统日期生成需要的字符串
      v_DateStr := TO_CHAR(SYSDATE, ('YYYYMMDD'));
      --生成产生流水号的序号
      BEGIN
        SELECT Decode(CurDat, v_DateStr, (SerialNum + 1), 1)
          INTO v_SerialNum
          FROM t_SerialNo
           FOR UPDATE;
      EXCEPTION
        WHEN NO_DATA_FOUND THEN
          v_SerialNum := 1;
          INSERT INTO t_SerialNo (CurDat, SerialNum) VALUES (v_DateStr, v_SerialNum);
      END;  --修改流水号参数
      UPDATE t_SerialNo SET CurDat = v_DateStr, SerialNum = v_SerialNum;
      COMMIT;
      --得到需要的流水号
      RETURN v_DateStr || Lpad(v_SerialNum, 7, '0');
    EXCEPTION
      WHEN OTHERS THEN
        ROLLBACK;
        RETURN NULL;
    END;
    /
    测试结果
    SQL> BEGIN
      2    FOR i IN 1 .. 10 LOOP
      3      dbms_output.put_line(getSerialNo());
      4    END LOOP;
      5  END;
      6  /
    201004200000001
    201004200000002
    201004200000003
    201004200000004
    201004200000005
    201004200000006
    201004200000007
    201004200000008
    201004200000009
    201004200000010PL/SQL 过程已成功完成。SQL> 
      

  6.   


    -- 做一个JOB,每天00:00:00的时候,重创建序列,从1开始,就OK了!
      

  7.   

    第一次用oracle 10g ,没有用过job .去查下 先
      

  8.   

    Set Serveroutput oncreate or replace procedure CreSeq(AsSql in varchar2) is
      iCurID  Integer;    -- 游标ID 
      iResult Integer;
    begin
      iCurID:= Dbms_Sql.Open_Cursor;
      Dbms_Sql.Parse(iCurID, AsSql, Dbms_Sql.V7); 
      iResult:= Dbms_Sql.Execute(iCurID);
      Dbms_Sql.Close_Cursor(iCurID);
    end;
    /create or replace function GetSqlValue(AsSql in varchar2) return Integer is
      iCurID  Integer;    -- 游标ID 
      iResult Integer;
      iReturn Integer;
    begin
      iCurID:= Dbms_Sql.Open_Cursor;
      Dbms_Sql.Parse(iCurID, AsSql, Dbms_Sql.V7); 
      Dbms_Sql.Define_Column(iCurID, 1, iReturn); 
      iResult:= Dbms_Sql.Execute(iCurID);
      if Dbms_Sql.Fetch_Rows(iCurID) > 0 then
        Dbms_Sql.Column_Value(iCurID, 1, iReturn);
      else
        iReturn:= -1;  
      end if;
      --Dbms_Sql.Close_Cursor(iCurID);
      Return iReturn;
    exception
      when Others then
        --Dbms_Output.Put_Line(SqlErrm);
        Return -2;
    end;
    /create or replace procedure GetMaxID(AdRq in Date, AnPlaces in Integer, AsOutOrderID out varchar2) is
      sSql       Varchar2(4000);
      sSeqName   Varchar2(30); -- 订单使用的Sequence名字
      nPlaces    Integer;
      nResult    Integer;
      nOrderID   Integer;
    begin
      AsOutOrderID:= '';
      -- 检查
      if AdRq is Null then
        Return;
      end if;
      -- 检查流水号位数
      if (Nvl(AnPlaces, 0) = 0) or (Nvl(AnPlaces, 0) < 0) then
        nPlaces:= 7;
      else
        nPlaces:= AnPlaces; 
      end if;
      
      sSeqName:= 'SEQ_ORDER' || To_Char(AdRq, 'YYYYMMDD');  select Count(1)
        into nResult
        from dual
       where Exists (select 1 
                       from all_Sequences
                      where Sequence_Name = Upper(sSeqName));
      
      if nResult = 0 then
        -- 创建Sequence
        sSql:= 'create Sequence ' || sSeqName || ' INCREMENT BY 1 START WITH 1 MAXVALUE ' || Rpad(' ', nPlaces + 1, '9') || ' CYCLE CACHE 10 ';
        --Dbms_output.put_line(sSql);    
        CreSeq(sSql);
      end if;
      
      -- 执行
      sSql:= 'select ' || sSeqName || '.NextVal' || ' from Dual';
      --Dbms_output.put_line(sSql);
      nOrderID:= GetSqlValue(sSql);
      
      if nOrderID <= 0 then
        AsOutOrderID:= '';
      else
        AsOutOrderID:= To_Char(AdRq, 'YYYYMMDD') || Lpad(To_Char(nOrderID), nPlaces, '0');
      end if;
      --Dbms_output.Put_Line(Nvl(AsOutOrderID, 'Error'));
    exception
      when others then
        Return;
        --Dbms_output.put_line(SqlErrm);
    end;
    /declare
      sOrderID varchar2(200);
    begin
      GetMaxID(sysdate, 8, sOrderID);
      dbms_output.put_line(sOrderID);
    end;
    /
    2010042000000015
    PL/SQL procedure successfully completed
    declare
      sOrderID varchar2(200);
    begin
      GetMaxID(sysdate, 8, sOrderID);
      dbms_output.put_line(sOrderID);
    end;
    /
    2010042000000016
    PL/SQL procedure successfully completed
      

  9.   

    用job来修改序列的时候有个问题create or replace procedure thispro2 as
    begin
      execute immediate
          'alter sequence seq_test increment by 1 start with 1 maxvalue 9999999 nocycle';
    end;SQL>  variable job2 number;
    SQL>  begin
      2   dbms_job.submit(:job2,'thispro2;',sysdate,'sysdate+5/1440');
      3   end;
      4   /
    SQL> begin
      2  dbms_job.run(:job2);
      3  end;
      4  /
    begin
    *
    第 1 行出现错误:
    ORA-12011: 无法执行 1 作业
    ORA-06512: 在 "SYS.DBMS_IJOB", line 406
    ORA-06512: 在 "SYS.DBMS_JOB", line 272
    ORA-06512: 在 line 2
    设置了每5分钟修改一次序列的值,但是执行job的时候就出这个问题
      

  10.   


    -- 序列只能删除,然后重建,不能用“alter”关键字修改!
      

  11.   

    --------------------------------------------------------------------------------------
    -- Step 1:给scott用户授权
    grant create sequence to scott;
    grant drop any sequence to scott;-- Step 2:切换到scott用户
    conn scott/bee56915-- Step 3:创建创建序列、创建删除序列的存储过程
    CREATE SEQUENCE order_id_seq INCREMENT BY 1 START WITH 1 MAXVALUE 9999999 NOCYCLE CACHE 10;create or replace procedure del_order_id_seq_proc
    IS
      sqlstr1 VARCHAR2(100);
      sqlstr2 VARCHAR2(100);
    BEGIN
      sqlstr1 := 'DROP SEQUENCE order_id_seq';
      sqlstr2 := 'CREATE SEQUENCE order_id_seq INCREMENT BY 1 START WITH 1 MAXVALUE 9999999 NOCYCLE CACHE 10';
      execute immediate sqlstr1;
      execute immediate sqlstr2;
    END;
    /exec del_order_id_seq_proc;
    select order_id_seq.nextval from dual;-- Step 4:定义作业名变量
    variable job_drop_seq1 number;-- Step 5:每隔1分钟调用作业(这个时间,你可以自己设置)
    begin 
      dbms_job.submit(:job_drop_seq1,'del_order_id_seq_proc;',sysdate,'sysdate+1/1440');
    end;
    /-- Step 5:例如:每天00:00:00调用作业
    begin 
      dbms_job.submit(:job_drop_seq1,'del_order_id_seq_proc;',sysdate,'trunc(sysdate+1)'); 
    end;
    /
    -- Step 5:查看下一个作业的执行时间(最下面的一个时间点2010-04-21 00:00:00 表示下一次的执行时间)
    column next_time for a20;
    select to_char(next_date,'YYYY-MM-DD HH24:MI:SS') as next_time from user_jobs;
      

  12.   

      主要是没有给scott权限,谢谢楼上的各位