项目是用oralce 10g + tomcat +jsp的
其中,有订单流水号,如年月日+7位流水号。以前做的东西里边因为订单少,就每次都去数据库取一次最后的订单号,再来生成新的订单好。但是现在这个项目里,每天的订单可能10W左右,而且下单时间比较集中。那该去怎么处理这个订单流水号?
还有就是,要对用户的所有操作,主要是查看/购买商品,点击/购买广告产品的记录。做这种操作轨迹记录,该怎么设计表,以及如何做查询优化,现在已有20W用户操作。。。
麻烦路过的大哥大姐帮帮忙,指点下。。。小弟先谢谢了
------解决方案--------------------
增加一个每日流水号的表,字段两个,一个是日期,一个是流水号(数值),先插入两年的记录,流水号都初始化为1。
每次需要新的流水号时,就用当前的日期去获取当天的流水号再补充0到7位,用了一个就把该表的流水号+1,相当于建立了一个动态的sequence。
------解决方案--------------------
用SEQUENCE吧 把SEQUENCE常驻在cache中 就不会丢失
第二个 应该是需要前台操作才能统计的吧 估计会要设计表格插入数据统计
20w每天产生100-200w数据很正常啊那就
你最终目的应该是要统计每个商品的 点击量 销售量吧
那就每天统计好 点击量 销售量 然后清掉 数据记录表
个人意见 一起学习
------解决方案--------------------
- SQL code
---------------- 若订单流水号是字符串型的话:(Oracle 10g) -----------------CREATE SEQUENCE order_id_seq INCREMENT BY 1 START WITH 1 MAXVALUE 9999999 CYCLE CACHE 10;SET SERVEROUTPUT ONDECLARE 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 ONDECLARE 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 ONDECLARE 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 ONDECLARE 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;/
------解决方案--------------------
使用for update强制串行,每天从1开始,生成唯一流水号
每天10W,性能没问题
- SQL code
--创建流水号表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 code
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;/2010042000000015PL/SQL procedure successfully completeddeclare sOrderID varchar2(200);begin GetMaxID(sysdate, 8, sOrderID); dbms_output.put_line(sOrderID);end;/2010042000000016PL/SQL procedure successfully completed