こんにちは。
Oracleのindex作成のポイントに付いて質問させて頂きます。

テーブルAに対して、インデックスAと言う名称のINDEXを作成するとします。

テーブルAの項目はP1,A1,A2,A3,A4と言う5ケの項目より成り立ちます。
(P1はテーブル作成時のプライマリーキーです。)

今、プログラム1・プログラム2・プログラム3からテーブルAのデータを利用していますが、速度が遅くそのためインデックスAを作成して改善するところです。

プログラム1では、A1,A2,A3をキーとしてデータを読み込んでいます。プログラム2ではA1とA4、プログラム3ではA1をキーとして読みこんでいます。
優先順位は、プログラム1が第1優先、プログラム2が第2優先、プログラム3が第3優先です。

システムに負荷を掛けたくないと言う理由からインデックスは1ケのみ作成するとします。
キー項目としては、どれを選定するべきでしょうか?

1)A1
2)A1,A2,A3
3)A1,A2,A3,A4

1)は汎用性があるように思えますが?
2)でプログラム1を優先させて、同時にプログラム2・3にもこのINDEXは適用されるのでしょうか?
それとも、全てを網羅した3)を使うべき?

ご経験者の方宜しくお願い致します。

このQ&Aに関連する最新のQ&A

A 回答 (5件)

>インデックスを張るとそれぞれ早くなるような感じがしてどうも感覚的にしっくり来てない状態ですが・・・。



 だから、実行計画を取得してください。SQL*PLUSで、SET AUTOTRACE ON。または、サンプルの件数が十分(最低でも千件)にあるなら、SET TIMING ONで、実行にかかった時間が表示されます。どちらもSQL*PLUSで使えます。


 インデックスの使用方法については、Oracle9iR2のマニュアルを見ているので、他のバージョンでは違う可能性があります。

この回答への補足

見えました。
実行計画で
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 INDEX (RANGE SCAN) OF 'インデックスA'

0 SELECT STATEMENT Optimizer=CHOOSE
1 0 TABLE ACCESS (BY INDEX ROWID) OF 'テーブルA'
2 1 INDEX (RANGE SCAN) OF 'インデックスA'
の違いでした。

補足日時:2003/10/17 15:38
    • good
    • 0
この回答へのお礼

有難う御座います。
マニュアル見ながら試行錯誤中です。

お礼日時:2003/10/17 14:16

>1)でも早くなるような感じで、どうもしっくり来てない>ですが、色々とやっています・・・。



件数少ないんじゃないんですか?

A1の条件だけで、かなり絞り込まれてるとか。
    • good
    • 0
この回答へのお礼

有難う御座います。
試行錯誤中です。

お礼日時:2003/10/17 14:14

A1,A2,A3


A1,A4

の2つを張れば、3つの処理すべてまかなえます。
あとは、どの処理を優先させるかでしょう。


ちなみに、
A1,A2,A3,A4
は、どの処理でも使用されません。
    • good
    • 0
この回答へのお礼

早速のご回答有難う御座います。
select * from テーブルA WHERE A1=定数 AND A2=定数 AND ・・・・
と言ったSQL文でインデックス変えながらテストしてます。
1)でも早くなるような感じで、どうもしっくり来てないですが、色々とやっています・・・。

お礼日時:2003/10/16 20:39

とりあえず3つとも作ってみては?



1を作る→各プログラムから実行されるSQLを擬似的に実行し、実行計画をとる→1を削除する→2を作る→(以下略)

でも、3のインデックスでも、プログラム2はインデックスを使いません。A1, A2, A3, A4の順で列を指定してインデックスを作ると、"A1", "A1&A2", "A1&A2&A3", "A1&A2&A3&A4"の条件を指定したとき、インデックスを使用します。

ということは、2で作ると、プログラム1とプログラム3はインデックスを使ってくれるわけですね。

なお、NULLを検索しようとすると、インデックスは使えません。
    • good
    • 0
この回答へのお礼

早速の回答有難う御座います。
おっしゃる通り只今全てのパターンを試しています。
インデックスを張るとそれぞれ早くなるような感じがしてどうも感覚的にしっくり来てない状態ですが・・・。

お礼日時:2003/10/16 20:30

インデックスに限らず、データベース設計はソフトウェアの使用目的やデータの性格 ( レコード件数や各項目のカーディナリティなど ) によって左右されますので、提示されている抽象的な情報だけでは最適解は判断できません。

    • good
    • 0
この回答へのお礼

早速のご回答ありがとう御座います。

お礼日時:2003/10/16 20:19

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています

関連するカテゴリからQ&Aを探す

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

Qsqlplusで表示が変なので、出力を整形したい。

いつもお世話になっています。

サーバにアクセスしてsqlplusで、
データを調べたいのですが、
出力形式が見づらくて困っています。

よくわからいのですが、
---------------------------
カラム名1
---------------------------
カラム名2
---------------------------
カラム名3
---------------------------
1の値 2の値
3の値
---------------------------
カラム名1
---------------------------
カラム名2
---------------------------
カラム名3
---------------------------

上記のように意味不明な形式で出てきます。

例えばこんな風に

select カラム1,カラム2,カラム3 from hoge;

カラム1 1の値
---------------------------
カラム2 2の値
---------------------------
カラム3 3の値

等のように分かりやすく表示できないでしょうか?

ちなみにOracle9iR2を使用しています。
sqlに関するツールは使用できないルールでして、あくまでsqlplusのコマンド上でみやすくしなければなりません。

分かりづらくですいませんが、皆さま、ご教授お願いします。

いつもお世話になっています。

サーバにアクセスしてsqlplusで、
データを調べたいのですが、
出力形式が見づらくて困っています。

よくわからいのですが、
---------------------------
カラム名1
---------------------------
カラム名2
---------------------------
カラム名3
---------------------------
1の値 2の値
3の値
---------------------------
カラム名1
---------------------------
カラム名2
---------------------------
カラム名3
-----------------------...続きを読む

Aベストアンサー

SQLPLUSを起動して、

SQL>set linesize 列数

でどうだ。

SQL>show linesize

で確認ができる。

QOracle(オラクル)で、日付時刻型の検索方法について

質問させていただきます。
データベースはオラクルを使っていて、
SQL文で、抽出するときにエラーが出て困っています。

日付時刻型が「2005/05/26 19:13:00」という感じで入ってます。
2005/05/26 を抽出したいのですが、
BETWEEN '2005/05/26 00:00:00' AND '2005/05/26 23:59:59'

だと、エラーでできません。
どなた様か、ご教授よろしくお願いしますm(_ _)m

Aベストアンサー

日付検索を行う場合は、以下のように書式を含める必要があります。

col BETWEEN TO_DATE('2005/05/26 00:00:00','YYYY/MM/DD HH24:MI:SS') AND TO_DATE('2005/05/26 23:59:59','YYYY/MM/DD HH24:MI:SS')

ただ、厳密には

col >= TO_DATE('2005/05/26', 'YYYY/MM/DD')
AND
col < TO_DATE('2005/05/27', 'YYYY/MM/DD')

と書くべきでしょうね。

QSELECTで1件のみ取得するには?

こんにちわ。
いまORACLE9iを使用している者です。

ACCESSでは
SELECT TOP 1 項目名 FROM テーブル名
ORDER BY 項目名;
で並べ替えたデータ群のうち,先頭の1件だけを
取ることができますが,
ORACLEでそのような機能(SQL)はあるでしょうか?
教えてください。
よろしくお願いします。

Aベストアンサー

order by と rownum を併用する場合は注意が必要です。

[tbl01]
cola | colb
------------
1000 | aaaa
1001 | bbbb

というデータがある場合、
select cola from tbl01 where rownum < 1 order by cola desc;
とすると、「1001」ではなく、「1000」が返されます。
これは、order by の前に rownum < 1 が適用されてしまうからです。

解決するには、
select aaa from (select cola aaa from tbl01 order by cola desc) where rownum = 1;
とすれば良いです。

QSIDとSERVICE_NAMEの違いとは?

tnsnames.oraの中の(CONNECT_DATA=に SIDだったりSERVICE_NAMEだったりしますが、どのような違いがあるのでしょうか?
どちらでもつながるのでいいかとは思いますが、何かメリット・デメリットでもあるのでしょうか?
それとも過去の遺物が未だ共存しているだけでしょうか?
SIDはインスタンスにつけられた名前だと知っていますが、SERVICE_NAMEってなんですか?

Aベストアンサー

SIDはインスタンスの識別子、service_nameはサービス名。
インスタンスとサービスの違いはRAC を勉強されるとよくわかると思います。

サービス名は初期化パラメータのservice_namesで設定します。
設定されていない場合は先述のとおりdb_unuque_name.db_domainになります。
(これが同義と誤解されやすい原因となっているわけですが)

ところで、service_namesパラメータですが、複数形になっていることからもわかるように、複数のサービス名をコンマ区切りで指定できるようになっています。

これをこのように使います。

2ノードRAC環境で、インスタンス1(SID=hoge1)、インスタンス2(SID=hoge2)があったとします。
ノードを意識することなく接続できるようにするためにクライアント側のtnsnames.oraにはこんな設定を追加します。

HOGE.EXAMPLE.COM
(DESCRIPTION =
(LOAD_BALANCE = ON)
(ADDRESS = (PROTOCOL = TCP)(HOST = host1)(PORT = 1521))
(ADDRESS = (PROTOCOL = TCP)(HOST = host2)(PORT = 1521))
(CONNECT_DATA = (SERVER = DECIDATED)(SERVICE_NAME = hoge.example.com))
)

インスタンス1とインスタンス2のservice_namesパラメータにhoge.example.comを追加します。すると、インスタンス1とインスタンス2にラウンドロビンで接続できるようになります。

ここで、もしtnsnames.oraのservice_name=...がSID=hoge1だったらどうなるでしょう?
インスタンス2のSIDはhoge2ですから一致せず、インスタンス2には接続できず、いつもインスタンス1に繋がってしまいます。

次に、一時的にメンテナンスのためにインスタンス2にアクセスしてほしくないケースを考えます。service_nameであれば、インスタンス2のservice_namesパラメータからhoge.example.comを削除することで(動的に変更できます)直ちにインスタンス1にのみ接続されるようにできます。

ここで、もしORACLE_SIDだったら・・・変更のためにインスタンスの再起動が必要になってしまいますね?

最後にservice_namesは複数登録できます。3ノードRAC環境において、オンライン処理(service_name=ONLINE)、バッチ処理(service_name=BATCH)があったとします。
バッチ処理は1つのノード(インスタンス1)でのみ処理したいとします。オンライン処理は3つのノードでしたいとします。

そんなとき、service_nameであれば、

<<サーバ側の初期化パラメータ>>
1:service_names = online, batch
2:service_names = online
3.service_names = online

<<クライアント側のtnsnames.ora>>

オンライン処理
ONLINE.EXAMPLE.COM
(DESCRIPTION =
(LOAD_BALANCE = ON)
(ADDRESS = (PROTOCOL = TCP)(HOST = host1)(PORT = 1521))
(ADDRESS = (PROTOCOL = TCP)(HOST = host2)(PORT = 1521))
(CONNECT_DATA = (SERVER = DECIDATED)(SERVICE_NAME = online.example.com))
)

BATCH.EXAMPLE.COM
(DESCRIPTION =
(LOAD_BALANCE = ON)
(ADDRESS = (PROTOCOL = TCP)(HOST = host1)(PORT = 1521))
(ADDRESS = (PROTOCOL = TCP)(HOST = host2)(PORT = 1521))
(CONNECT_DATA = (SERVER = DECIDATED)(SERVICE_NAME = batch.example.com))
)

と、クライアント側では接続先サーバを気にすることなく構成できますね?
BATCHのノードを1から2にしたい場合の変更はサーバ側のみでできますよね?
serivce_namesの"batch"設定をノード2に移すだけです。

SIDはインスタンスの識別子、service_nameはサービス名。
インスタンスとサービスの違いはRAC を勉強されるとよくわかると思います。

サービス名は初期化パラメータのservice_namesで設定します。
設定されていない場合は先述のとおりdb_unuque_name.db_domainになります。
(これが同義と誤解されやすい原因となっているわけですが)

ところで、service_namesパラメータですが、複数形になっていることからもわかるように、複数のサービス名をコンマ区切りで指定できるようになっています。

これをこのように...続きを読む

QOracleの排他制御について教えてください

質問内容は結論から言うと、
INSERT文の時の排他制御について
知りたい。

以下の私の認識を踏まえた上で、
INSERT文の排他制御について
質問させてください。
なお、私の認識に誤りがあれば
指摘してください。

### 私の認識 start ######

1)Oracle
では、select文の時に
for updateを
書かなければ、なんのロックもかからず、
読み取り専用リソースへのアクセスで
ない限り、
ダーティーリードの可能性がある。

2)
select文で for update
を指定した場合は
該当行について
共有ロックがかかる。
行単位の共有ロックがかかる。
その際、
他のトランザクションが
for updateつきで
selectしてきても、
共有ロック同士なので、
互い排他制御しない。

(3)
update 文の場合は
該当行について、
占有ロックがかかる
行単位の占有ロックがかかる。

(4)
INSERT文の時には、
ロックをかけようにも
INSERT前の段階では、
ロック対象行は存在しない。
複数のトランザクションが
INSERTした行のPK
の値が偶然同じであった場合
ロストアップデートの危険があるので
私の創造では、INSERT文の時は
テーブル全体をロックしないと、
うまくいかないように思えます。

(5)
update, insert文については、
Oracleでは、自動的に該当行について
占有ロックを行う。
なお、INSERT文については、
下記の質問事項における疑問点
が解消されていないため、
行単位なのかどうか、私の中では
自身がもてないのが現状です。
### 私の認識 end ######

### 主な質問内容 start ###
私の認識の(4)を踏まえた上で
INSERT文の時のはいた制御
の範囲や挙動について、
教えてください。
### 主な質問内容 end ###

以上です。

質問内容は結論から言うと、
INSERT文の時の排他制御について
知りたい。

以下の私の認識を踏まえた上で、
INSERT文の排他制御について
質問させてください。
なお、私の認識に誤りがあれば
指摘してください。

### 私の認識 start ######

1)Oracle
では、select文の時に
for updateを
書かなければ、なんのロックもかからず、
読み取り専用リソースへのアクセスで
ない限り、
ダーティーリードの可能性がある。

2)
select文で for update
を指定した場合は
該当行について
共有ロッ...続きを読む

Aベストアンサー

#2 補足です。
2)
SELECT FOR UPDATE文は
NO WAIT オプションをつけたときは即時エラーに、
つけないときはロック解除待ちになります。
どちらを使うかはアプリケーションの作り方のポリシーによります。

セッション=クライアントとサーバの間の接続。データベースに接続してから切断するまでの間の接続が確立している状態

トランザクション=データベースの処理をひとまとまりにしたモノ。たとえば、口座Aから口座Bへの振り込み処理の場合、口座Aからの引き出し、口座Bへの振り込みの処理を1トランザクションとして扱います。どちらかが失敗した場合はロールバック(巻き戻し)、成功した場合はコミット(確定)します。

業務用アプリケーションの場合、大抵、1回のセッションの中では複数回のトランザクションが発生します。複数のユーザーがそのアプリケーションを利用していればその数だけセッションが張られます。(Webアプリに関してはその限りではないですが)

デッドロック=
Aと言うセッションがトランザクション内で
1-1 表Xのa行に更新をかけます。
1-2 次に表Yにb行に更新をかけます。
1-3 コミットします(トランザクションの終了)。

同時に
Bと言うセッションがトランザクション内で
2-1 表Yにb行に更新をかけます。
2-2 次に表Xのa行に更新をかけます。
2-3 コミットします(トランザクションの終了)。

これが、1-1 2-1 1-2 2-1 1-3 2-3
と言う順番で実行された場合デッドロックが発生します。つまりAは、X-aにロックをかけたままY-bにロックをかけようとして待ち状態になる。逆にBは、Y-bにロックをかけたまま、X-aにロックをかけようとして待ち状態になる。この状態をデッドロックと呼びます。

なお、Oracleでは、UNDOセグメントではなくロールバックセグメントと呼びます。

a)アーキテクチャに突っ込んだ話になるので、詳しくはOracle データベース概要のドキュメントを読んでください。

基本的に、SELECT中に他のセッション(アプリケーションの方が良いかな?)からの更新が確定した場合、SGA(システムグローバルエリア=Oracleサーバの共有メモリスペース)に前のデータのバックアップを取ります。これによって読み取り一貫性を保証します。ここにデータが入りきらない場合はデータベースのロールバックセグメント(たしか)に吐き出します。

b)
簡単に言えば、Oracleは、行ごとにロックフラグなどを記録する領域を持っています。マニュアルなどに書いてなければおそらく企業秘密です。

#2 補足です。
2)
SELECT FOR UPDATE文は
NO WAIT オプションをつけたときは即時エラーに、
つけないときはロック解除待ちになります。
どちらを使うかはアプリケーションの作り方のポリシーによります。

セッション=クライアントとサーバの間の接続。データベースに接続してから切断するまでの間の接続が確立している状態

トランザクション=データベースの処理をひとまとまりにしたモノ。たとえば、口座Aから口座Bへの振り込み処理の場合、口座Aからの引き出し、口座Bへの振り込みの処理を1トラン...続きを読む

QOracle 10gで順序sequenceの作成(定義)した内容を見るには?

Oracle 10gで順序sequenceの作成(定義)した内容を見るにはどうしたらよいのでしょうか?
desc sequence_nameでは SP2-0381: DESCRIBE sequenceは使用できませんと表示されます。

Aベストアンサー

 次の検索を実行してください。

 select * from user_sequences where sequence_name = "find_sequence";

where句のfind_sequeceの所は、探したいsequenceの名前を入れてください。もし、where句を省略すると自分の保有するすべての順序が出てきます。
 出てくる各列の意味は、次の通りです。

 sequence_name 順序名
 min_value 順序の最小値
 max_value 順序の最大値
 increment_by 順序の間隔
 cycle_flag 順序が最大値の後、最初の値に戻るかどうか
 order_flag 順序番号が順番に生成されるかどうか
 cache_size 順序のキャッシュの量

 この表は、システム表の一つで、順序の定義すべてを管理しています。(正確には、システム表へのビューですが。)
 もし、あなたに、それなりの権限があるのであれば、all_sequences表を検索すれば、システムにおいてあなたが使用できるすべての順序がリストできますし、dba_sequencesを検索すれば、システム上に存在するすべての順序をリストできます。ただし、dba_ で始まるシステム表の検索は、権限が必要です。また、与えられた権限にかかわらず、この表への挿入・削除・変更は、すべて不可です。念のため。

 次の検索を実行してください。

 select * from user_sequences where sequence_name = "find_sequence";

where句のfind_sequeceの所は、探したいsequenceの名前を入れてください。もし、where句を省略すると自分の保有するすべての順序が出てきます。
 出てくる各列の意味は、次の通りです。

 sequence_name 順序名
 min_value 順序の最小値
 max_value 順序の最大値
 increment_by 順序の間隔
 cycle_flag 順序が最大値の後、最初の値に戻るかどうか
 order_flag 順序番号が順番に生成...続きを読む

Q3つの表の外部結合

表A、B、Cの3つがあり、Aのすべての行を出力したいと考えています。
外部結合を用いるのだとは思うのですが、3つの表に対して行う場合の
書き方がわからず困っています。
ご教授いただけないでしょうか?
select * from a,b,c
where a.商品ID =b.商品ID (+) and b.商品ID (+) =c.商品ID (+)
としてみましたが、うまくいきませんでした。

Aベストアンサー

ansi構文の趣旨からいえば、結合条件と絞り込み条件は分けて書くので・・

select *
from a
left join b on (a.商品ID =b.商品ID)
left join c on (b.商品ID =c.商品ID)
where a.年月 = 任意の値

と書くのが一般的でしょうね。

QSQLPLUSで結果を画面に表示しない

1つ教えて下さい。
SQLPLUSでselect文で抽出結果をspool等でファイルに
出力したいのですが、
この時、コマンドを打った画面の方には結果を出さないように
する事はできるのでしょうか?
件数が膨大な為、画面にずっと結果が出力され続けており
これを止めたいです。

Aベストアンサー

「termout」という、ファイルから実行したコマンドの出力表示を抑止するパラメータがあります。

set termout off を実行してから、SQLスクリプトでスプールすれば画面には表示されません。

これらのパラメータはSQL*Plusのマニュアルに記載されています。

QChr(13)とChr(10)の違いは?

myStr = Replace(myStr, Chr(13), "")

myStr = Replace(myStr, Chr(10), "")

で、改行を置換しているのですが、どちらかでも改行できる時や
どちらかじゃないと改行できない時があります。

そもそもChr(13)とChr(10)の違いはなんでしょう?
どちらも改行ですよね?
何が違うのでしょう?

Aベストアンサー

こんにちは。お邪魔します。

Chr(10) ・・・ ラインフィード ・・・ 略して、Lf

Chr(13) ・・・ キャリッジリターン ・・・ 略して、Cr

改行文字に何を使うのかはアプリケーションが規定するものです。

Win・Office環境では
上のふたつを組合わせた改行[CrLf]を使うことが多いと思います。
次に[Lf]、そして、[Cr]

なので、ソースによっては
  myStr = Replace(myStr, vbCrLf, "")
と、一発で置換できるケースも少なくないです。
■ソースごとに改行文字を確認しておくことから始めた方が有利になります。■

ひとまず、VBAでの改行の扱いに慣れるには
■VBAで用意された文字列定数について知っておいた方がよいと思います。■
 VBE(Visual Basicの編集画面)が開いている状態で、
 F2 キー → オブジェクトブラウザー起動
 検索小窓に、vbCrLf、とタイプして、検索ボタン
 VBA.Constantsクラスのメンバーが表示され
 その中にすべての改行文字(文字列定数)が含まれています。
 そのまま、F1 キーでヘルプを表示します。
詳しい説明はヘルプを読む方がいいでしょう。

実践的な話として、
Chr(10)やChr(13)は関数の戻り値です。
対して、
vbLfやvbCr(またはvbCrLf)は定数です。
定数で済ませられるなら、定数の方が何かと有利です。
定数の名前は略号ですから、実態をイメージし易くなっています。
定数の扱いに慣れることをお奨めします。
例)
  myStr = Replace(myStr, vbLf, "")
  myStr = Replace(myStr, vbCr, "")
  myStr = Replace(myStr, vbCrLf, "")

もしも文字列定数を先に覚えていたなら、疑問にもならなかったのかも知れませんね。
私の場合は、改行の何たるかを覚える前に文字列定数覚えていて、困ることありませんでしたから。

以上、ご参考まで。

こんにちは。お邪魔します。

Chr(10) ・・・ ラインフィード ・・・ 略して、Lf

Chr(13) ・・・ キャリッジリターン ・・・ 略して、Cr

改行文字に何を使うのかはアプリケーションが規定するものです。

Win・Office環境では
上のふたつを組合わせた改行[CrLf]を使うことが多いと思います。
次に[Lf]、そして、[Cr]

なので、ソースによっては
  myStr = Replace(myStr, vbCrLf, "")
と、一発で置換できるケースも少なくないです。
■ソースごとに改行文字を確認しておくことから始めた方が有利...続きを読む


このQ&Aを見た人がよく見るQ&A

人気Q&Aランキング

おすすめ情報