備忘録

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

指定した精度より小さい桁に値を設定すると四捨五入される

create table T ( C number(3));
insert into t values (123.5);
select * from t;
としたとき、123が取れると思ったが、124となった。
指定した精度より下は無視されるのが正しいと思うが。。
マニュアルを見ると四捨五入の例があった。

入力:7,456,123.89
指定:NUMBER(9,1)
格納方法 :7456123.9

試したら、TIMESTAMPも精度を指定でき、同じような動きになった。

SELECT FOR UPDATE対象が別セッションで更新され、条件に合わなくなったらどうなるか?

1.セッションA で SELECT FOR UPDATE
  副問い合わせで最大値を求めそれを取得。値が10,20とあったら、20のレコードをロックされる。
2.セッションB で同条件で SELECT FOR UPDATE
  同じく値20のレコードを待つ。
3.セッションA で、2.の条件に合わない
  20→0と値を変更しコミット。
4.セッションB ではどうなるか?

値10のレコードが取れるか?データなしとなるか?
結果は、データなしとなる。
まあ、考えればわかる。
10を返そうとするには、副問い合わせを再実行しないといけない。
下手すれば無限ループ。

以下、試した結果。


-- ↓準備
create table T ( C number);
insert into t values (10);
insert into t values (20);
commit;
-- ↑準備

-- ↓セッションA
select * from t
where c = (select max(c) from t)
for update;
-- ↑セッションA

-- ↓セッションB
SQL> select * from t
2 where c = (select max(c) from t)
3 for update;
-- ↑セッションB

-- ↓セッションA
update t set c=0 where c = 20;
commit;
-- ↑セッションA

-- ↓セッションB
レコードが選択されませんでした。
-- ↑セッションB

データ0件なのに検索が遅い

ブログに始めてのコメントがあったので、久しぶりに再会。

開発環境で0件なのにSELECTが遅いことがあったので、結果はほぼ想像できていたが調べてみた。

  1. V$SQLから遅いSQLのSQLIDを探す

  2. SELECT a.SQL_ID, a.SQL_TEXT, a.* FROM V$SQL a WHERE a.SQL_TEXT LIKE '%なんたら%';


  3. 実行計画を見る

  4. SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR('見つけたSQL_ID'));


  5. 使っているオブジェクトがぶっ壊れていないか調べる

  6. SELECT a.STATUS, a.* FROM ALL_OBJECTS a WHERE a.OBJECT_NAME = 'テーブル名なりインデックス名';


  7. セグメントのサイズを調べる
  8. SELECT TRUNC(a.BYTES/1024/1024/1024, 2) "サイズ(GB)", a.* FROM DBA_SEGMENTS a WHERE a.SEGMENT_NAME = 'テーブル名なりインデックス名';


    0件なのにデカイことがここでわかる。

無駄にデカイからFULL SCAN時にそのセグメントを舐め回さないといけないから遅かった。
なぜでかいか?マニュアルのこの辺りを見ると良いかと。

  • オンラインでセグメントを縮小する方法の詳細は、『Oracle Database管理者ガイド』を参照してください。

  • TRUNCATE TABLEの構文およびセマンティクスについては、『Oracle Database SQL言語リファレンス』を参照してください。


再編成かtruncateをせよってこと。
開発環境のユーザにDROP TABLE権限がなく、TRUNCATEができなかったからセグメントが広がりっぱなしだったんでしょう。
DROP TABLE権限をつけるのは躊躇するだろうから、TRUNCATE権限っていうのがあれば良いんだけどね。

outパラメータ

select * from v$version;

BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
PL/SQL Release 11.2.0.3.0 - Production
CORE 11.2.0.3.0 Production
TNS for 64-bit Windows: Version 11.2.0.3.0 - Production
NLSRTL Version 11.2.0.3.0 - Production

set serveroutput on

CREATE TABLE OUT_PARAM (
pNum NUMBER(10) default 1
,pCHR CHAR(10) default '1'
,pVCR VARCHAR2(10) default '1'
,pDT DATE default sysdate
,pTS TIMESTAMP default systimestamp
,pNV NVARCHAR2(10) default '1'
,pNC NCHAR(120) default '1'
);

create or replace PACKAGE BODY OUT_PARAM_TEST as

TYPE T_OUT_PARRAM IS RECORD (
pNum NUMBER(10) default 1
,pCHR CHAR(10) default '1'
,pVCR VARCHAR2(10) default '1'
,pDT DATE default sysdate
,pTS TIMESTAMP default systimestamp
,pNV NVARCHAR2(10) default '1'
,pNC NCHAR(120) default '1'
);

PROCEDURE HOGE(
pInt OUT PLS_INTEGER
,pNum OUT NUMBER
,pCHR OUT CHAR
,pVCR OUT VARCHAR2
,pDT OUT DATE
,pTS OUT TIMESTAMP
,pNV OUT NVARCHAR2
,pNC OUT NCHAR
,pRT OUT OUT_PARAM%ROWTYPE
,pRT2 OUT OUT_PARAM%ROWTYPE
,pRT3 OUT OUT_PARAM%ROWTYPE
) IS
BEGIN
DBMS_OUTPUT.PUT_LINE('pInt[' || pInt || ']');
DBMS_OUTPUT.PUT_LINE('pNum[' || pNum || ']');
DBMS_OUTPUT.PUT_LINE('pCHR[' || pCHR || ']');
DBMS_OUTPUT.PUT_LINE('pVCR[' || pVCR || ']');
DBMS_OUTPUT.PUT_LINE('pDT[' || pDT || ']');
DBMS_OUTPUT.PUT_LINE('pTS[' || pTS || ']');
DBMS_OUTPUT.PUT_LINE('pNV[' || pNV || ']');
DBMS_OUTPUT.PUT_LINE('pNC[' || pNC || ']');
DBMS_OUTPUT.PUT_LINE('pRT.pNum[' || pRT.pNum || ']');
DBMS_OUTPUT.PUT_LINE('pRT2.pNum[' || pRT2.pNum || ']');
DBMS_OUTPUT.PUT_LINE('pRT3.pNum[' || pRT3.pNum || ']');
END HOGE;


PROCEDURE TEST IS
pInt PLS_INTEGER := 1;
pNum NUMBER(10) := 1;
pCHR CHAR(10) := '1';
pVCR VARCHAR2(10) := '1';
pDT DATE := SYSDATE;
pTS TIMESTAMP := SYSTIMESTAMP;
pNV NVARCHAR2(10) := '1';
pNC NCHAR(120) := '1';
pRT OUT_PARAM%ROWTYPE;
pRT2 T_OUT_PARRAM;
TYPE tArray IS TABLE OF T_OUT_PARRAM INDEX BY BINARY_INTEGER;
pTA tArray;
BEGIN
pRT.pNum := '2';
pRT2.pNum := '3';
HOGE(
pInt
,pNum
,pCHR
,pVCR
,pDT
,pTS
,pNV
,pNC
,pRT
,pRT2
,pTA(0)
);
END TEST;

END OUT_PARAM_TEST;
/

exec OUT_PARAM_TEST.test;
pInt[]
pNum[]
pCHR[]
pVCR[]
pDT[]
pTS[]
pNV[]
pNC[]
pRT.pNum[]
pRT2.pNum[]
pRT3.pNum[]

PL/SQLプロシージャが正常に完了しました。

Intelligent Data Placement

Orale11g の ASM 新機能で、Intelligent Data Placement というのがあるのを知った。
HDD はディスクの内側より外側のほうが速いから、内側をCOLD、外側をHOTと定義して使い分けるという機能。
惜しむらくべきは、データファイル単位でしか出来ないこと。
⇒いちいちテーブルスペースを分けないと使えない。
もっとインテリジェントじゃないと使えないですね。同じテーブルスペースでも勝手に使い方を学習してデータを移動とかしてくれるのならいいのに。
SSDとかHDDとかごっちゃ混ぜで適当に振り分けてくれると何も考えなくていいのに。

【検証資料】Automatic Storage Management Intelligent Data Placementによるパフォーマンス・チューニング
次のページ

FC2Ad

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。