最初のクエリが2番目のクエリよりも高速になる理由を理解しようとしています。
SELECT * FROM DBADMIN.CR_TICKET WHERE QUEUE_ID=005555 AND STATUS=4
と
SELECT TICKET_ID FROM DBADMIN.CR_TICKET WHERE QUEUE_ID=005555 AND STATUS=4
最初の実行には約1分かかり、すべてのフィールドが返されます。2つ目は、時間がかかりすぎるため、数分後に停止します。TICKET_IDは有効な列名です。私はデータベースとSQLを初めて使用し、Oracle InstantClient11を参照してvb.netを使用しています。
Using connection As New OracleConnection()
Dim command As OracleCommand = connection.CreateCommand()
Dim reader As OracleDataReader = command.ExecuteReader()
Dim str As String
Dim strFieldName As String
Dim strFieldType As String
Dim sql As String = "SELECT * FROM DBADMIN.CR_TICKET WHERE QUEUE_ID=005555 AND STATUS=4"
connection.ConnectionString = connectionString
connection.Open()
command.CommandText = sql
While reader.Read()
str = ""
strFieldName = ""
strFieldType = ""
For e = 0 To reader.FieldCount - 1
strFieldName = reader.GetName(e)
strFieldType = reader.GetDataTypeName(e)
str = str & strFieldName & " " & strFieldType & ": " & reader(e).ToString & vbCrLf
Next
Console.Write(str & vbCrLf & vbCrLf)
End while
更新3/4/13:
まず、すばらしいアドバイスをありがとうございました。最終的にsql plusを実行して、次の実行プランを返すことができました。昨日たくさん読んだのですが、クエリが遅い理由の1つは、検索している列がインデックスに登録されていないことです。主キー列(すべてのテーブルに存在する)がデフォルトでインデックス付けされていることを発見しました。SQL文字列を次のように変更しました。
SQL> SELECT * FROM DBADMIN.CR_TICKET WHERE TICKET_ID > 'CR00000000' AND STATUS=4 AND (QUEUE_ID=005555 OR QUEUE_ID=005556) ORDER BY PRIORITY, TROUBLE_START;
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)
| Time |
--------------------------------------------------------------------------------
------------
| 0 | SELECT STATEMENT | | 1 | 401 | 6 (17)
| 00:00:01 |
| 1 | SORT ORDER BY | | 1 | 401 | 6 (17)
| 00:00:01 |
|* 2 | TABLE ACCESS BY INDEX ROWID| CR_TICKET | 1 | 401 | 5 (0)
| 00:00:01 |
|* 3 | INDEX RANGE SCAN | CRT_TID_IDX | 1 | | 4 (0)
| 00:00:01 |
--------------------------------------------------------------------------------
これはかなり速く実行されています。私の元のクエリは、ステートメントと一致させるためにデータベース内のすべてのレコードを読み取っていることを学びました。クエリを少し異なる方法で構造化してインデックス付き列を含めることにより、基本的にメインデータベースの一部のみを検索します。
SQL> SELECT * FROM DBADMIN.CR_TICKET WHERE QUEUE_ID=005555 AND STATUS=4 AND PRIORITY=1;
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)
| Time |
--------------------------------------------------------------------------------
------------
| 0 | SELECT STATEMENT | | 1 | 401 | 14864 (1)
| 00:02:59 |
|* 1 | TABLE ACCESS BY INDEX ROWID| CR_TICKET | 1 | 401 | 14864 (1)
| 00:02:59 |
|* 2 | INDEX RANGE SCAN | CRT_STAT_IDX | 230K| | 408 (2)
| 00:00:05 |
SQL> SELECT DBADMIN.CR_TICKET.TICKET_ID FROM DBADMIN.CR_TICKET WHERE QUEUE_ID=005555 AND STATUS=4 AND PRIORITY=1;
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)
| Time |
--------------------------------------------------------------------------------
------------
| 0 | SELECT STATEMENT | | 1 | 24 | 14845 (1)
| 00:02:59 |
|* 1 | TABLE ACCESS BY INDEX ROWID| CR_TICKET | 1 | 24 | 14845 (1)
| 00:02:59 |
|* 2 | INDEX RANGE SCAN | CRT_STAT_IDX | 230K| | 408 (2)
| 00:00:05 |
--------------------------------------------------------------------------------
更新2013年5月25日
助けてくれてありがとう、感謝します。私はついにこのプロジェクトを再訪する機会があり、あなたの提案した質問を試しました。最初の1つは正常に実行され、次の2つは結果を返しませんでした。インデックス機能についておっしゃいましたね。これにより、データベースに永続的なインデックスが作成されますか?私はそれをしたくない。
select status, priority, count(*)
from dbadmin.cr_ticket
group by status, priority;