田中健二のブログ

田中健二のブログ

ブログの説明を入力します。

Amebaでブログを始めよう!
一億件データを持つテーブルABC。。。
次のような、クエリを投げたら直ぐ結果が出るのか?
何分、何秒かかるか?

SELECT * FROM ABC

このクエリの結果は直ぐ出る。
データベースにはARRAY SIZEというものがある。
SELECTクエリを投げたら、DBはARRAY SIZE分、テーブルからデータを取る。
ARRAY SIZEに到達すると、DBは結果をクライアントに変換してくれる。

SELECT * FROM ABCは条件のないクエリで、ABCテーブルの全ての
レコードが正しい結果となるため。
ARRAY SIZEに到達するまで、時間がかからないのだ。
これが部分範囲処理。。。

次のSQLは何分、何時間かかるか予想つかない。

SELECT * FROM ABC ORDER BY NAME

上記のSQLは一億件を全部ソートしないと、正しい結果になれない。
これが、全体範囲処理。。

普通、データはページングして画面に表示する。
要は、全体範囲処理を避け、部分範囲処理にして
速くて正しいSQL組み方があるのだ。

*ORDER BYを避ける方法
*部分範囲処理を図る方法を考えて見よう!!!


Cartesian product 条件なしの結合


JOINというのは重い処理なのか? よく現場で聞こえるんだ。JOINはオソイって。

JOINには多様な方法がある。NESTED LOOP, SORT MERGEなど。。。

実行計画を確認することが重要。OPTIMIZERがどういう風にSQLを解決してくれるのかを最後まで目で確かめることが必要だ。私たちは問題を解く学生じゃない。問題を解くのはOPTIMIZERなのだ。

OPTIMIZERは高い、OPTIMIZERに仕事をさせてみよう!!


Cartesian productは条件のないjoin


Cartesian product
は統計性帳票などで強い力を発揮してくれる。


テーブル EMP

EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO

7369 SMITH CLERK 7902 1980-12-17 800 20

7499 ALLEN SALESMAN 7698 1981-02-20 1600 300 30

7521 WARD SALESMAN 7698 1981-02-22 1250 500 30

7566 JONES MANAGER 7839 1981-04-02 2975 20

7654 MARTIN SALESMAN 7698 1981-09-28 1250 1400 30

7698 BLAKE MANAGER 7839 1981-05-01 2850 30

7782 CLARK MANAGER 7839 1981-06-09 2450 10

7788 SCOTT ANALYST 7566 1987-04-19 3000 20

7839 KING PRESIDENT 1981-11-17 5000 10

7844 TURNER SALESMAN 7698 1981-09-08 1500 0 30

7876 ADAMS CLERK 7788 1987-05-23 1100 20

7900 JAMES CLERK 7698 1981-12-03 950 30

7902 FORD ANALYST 7566 1981-12-03 3000 20

7934 MILLER CLERK 7782 1982-01-23 1300 10


テーブル DEPT

DEPTNO DNAME LOC

10 ACCOUNTING NEW YORK

20 RESEARCH DALLAS

30 SALES CHICAGO

40 OPERATIONS BOSTON



上記の二つのテーブルを利用して、次のような結果を出してくれるsqlを組んでみよう。。




部署名 SUM(MANAGER) SUM(SALESMAN) SUM(CLERK) SUM(EX) SUM(部署別計)

ACCOUNTING 2450 1300 5000 8750

RESEARCH 2975 1900 6000 10875

SALES 2850 5600 950 9400

総計 8275 5600 4150 11000 29025



この結果は全社員の部署別、ジョブ別の給料の総計表である。

ポイントは総計があるレコードを作り出すためのsql組み方なのだ。

こういう統計性帳票を作るため、帳票ツールを機能を利用したり、何度もSQLを実行させ、その結果を画面に表示したりするケースが多いと思うが。

一番、はやい処理は?? 私は一つのSQLを組むことが一番速いと考えている。その理由は沢山ある(知りたい??今度にしよう)。




SQL作成の鉄則。。。

*同じテーブルは一回のみ読む

*恥ずかしくないSQL作成する

*クライアント、サーバ環境を理解し、SQLを組む

*集合的な考え方、SQLは一般的なプログラムのように組まないこと

*などなど、沢山あるが。。。



正解>

SELECT DECODE(FLAG,'1',DNAME,'総計') 部署名, SUM(MANAGER),SUM(SALESMAN),SUM(CLERK),SUM(EX),SUM(部署別計) FROM

(SELECT DNAME, MANAGER,SALESMAN,CLERK,EX,部署別計 FROM

(SELECT DEPTNO,


SUM(DECODE(JOB,'MANAGER',SAL)) "MANAGER",


SUM(DECODE(JOB,'SALESMAN',SAL)) "SALESMAN",


SUM(DECODE(JOB,'CLERK',SAL)) "CLERK",


SUM(DECODE(JOB,'MANAGER',NULL,'SALESMAN',NULL,'CLERK', NULL, SAL)) "EX",


SUM(SAL) "
部署別計"

FROM EMP

GROUP BY DEPTNO) A, DEPT B

WHERE A.DEPTNO = B.DEPTNO) A,

(SELECT '1' FLAG FROM DUAL

UNION ALL

SELECT '2' FROM DUAL) B

GROUP BY DECODE(FLAG,'1',DNAME,'総計')

ORDER BY DECODE(FLAG,'1',DNAME,'総計')










開発者、SEなら毎日触っているSQL。。

私も開発者としてSQLで活躍しています(あ~ウソ)

次のSQLを実行してみようぉぉぉ~

Table DEPT (oracleのSCOTTユーザ)

DEPTNO DNAME LOC
---------- -------------- -------------
10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON


>>①SELECT * FROM DEPT WHERE ROWNUM = 1
>>②SELECT * FROM DEPT WHERE ROWNUM = 2
>>③SELECT * FROM DEPT WHERE ROWNUM < 2
>>④SELECT * FROM DEPT WHERE ROWNUM > 1


どうして、②④は結果が0件なの??

まず、ROWNUMというのは、データが要求され、テーブルオブジェクトからデータがとられる順番です。
要は、テーブルからデータが出る順番のことです。

上記の②④SQLは一番目のレコードにROWNUM = 2の条件が
FALSEとなるため、次のレコードにROWNUM割当(rownum increment)ができないのが
理由です。なので、0件。

--------------------------------------

おまけに、SQLの実行順番について。。。
select X,Y,Z, ......①
ROWNUM ......②
from t ......③
where ......④
group by ......⑤
having ......⑥
order by ......⑦

実行順番はどうなるんです?(ハハ~~)
正解は ③④②①⑤⑥⑦

この実行順番の説明は
データベースのアーキテクチャー、メモリ構成などについて
知っている方は難しくないと思います。

TRACE及び実行計画プランを見たことがある方は
SELECT文を投げた後、データベースのoptimizerがどういう風に
SQLを分析し、結果を作り出すのかについてご存知だと思います。^^

これからは、単純にSQLを組むのではなく、
データベースシステムに優しい(笑)SQLを目指して記事を書きたいと思います。