프린트 하기

OS 환경 : Oracle Linux 8.4 (64bit)

 

DB 환경 : Oracle Database 23.7.0.25.01 ai for Oracle Cloud and Engineered Systems, Free

 

방법 : 오라클 23ai 신기능 Select AI 사용 테스트(non-adb)

오라클 23.7 버전부터 adb가 아닌 일반 온프레미스db에도 dbms_cloud 패키지를 설치할 수 있음
(2025년 04월 기준 아직까지 23.7 일반 버전은 나오지 않았지만 Oracle Cloud and Engineered Systems 버전과 Free 버전으로 테스트함)

아래 글 작성시에는 free 버전 설치시 23.4버전이 설치되었지만 지금은 23.7 버전으로 설치됨

참고 : Oracle Linux 8.4에 Oracle 23ai Free RPM 설치 및 삭제 가이드 ( https://positivemh.tistory.com/1095 )

하지만 dbms_cloud가 23.7에 기본적으로 탑재되어있지 않고 수동으로 설치를 해주어야함
이전 게시글에서 23.7 버전에 dbms_cloud를 설치하는 방법을 설명했음
이 게시글은 dbms_cloud가 설치된 상태에서 진행함
참고 : 오라클 23ai 신기능 dbms_cloud 설치(non-adb) ( https://positivemh.tistory.com/1203 )

 

 

본문에서는 Select AI 기능을 설명하고 dbms_cloud 패키지중 하나인 dbms_cloud_ai를 이용해 Select AI를 테스트해봄

 

 

Select AI 란?
Select AI는 23ai의 신기능으로 출시 초기에는 Oracle Cloud Infrastructure(OCI)상의 Oracle Autonomous Database(ADB)에서만 구동 가능했지만
23.7버전부터 non-adb에서도 실행이 가능함
Select AI는 자연어를 사용하여 데이터베이스에 쿼리할 수 있는 기능임
대규모 언어 모델(LLM)을 활용하여 사용자의 자연어 입력을 Oracle SQL로 변환함
Select AI는 자연어 프롬프트를 처리하고, 데이터베이스의 메타데이터로 이를 보완한 후, SQL 쿼리를 생성하고 실행함
이를 통해 사용자는 SQL 문법을 몰라도 자연어로 데이터베이스와 상호작용하여 원하는 정보를 얻을 수 있음
Select AI는 벡터 임베딩 생성부터 벡터 저장소를 활용한 의미적 유사성 검색을 통해 사용자의 프롬프트에 기반한 관련 콘텐츠 검색까지 검색 증강 생성(RAG) 프로세스를 자동화함
그 외에도 합성 데이터 생성, 대화 내역 지원 등의 기능이 있으며, 모두 SQL 인터페이스를 통해 제공됨

 

 

Select AI에서 지원하는 AI 공급업체

공급업체 지원 LLM 예시 주요 용도
OCI Generative AI meta.llama-3.1-70b-instruct (default)
meta.llama-3.1-405b-instruct
meta.llama-3.2-90b-vision-instruct
etc..
runsql, showsql, explainsql, narrate, chat 등 모든 Select AI 작업
Azure OpenAI GPT-4o
GPT-4
GPT-4 Turbo with Vision
etc..
자연어 프롬프트, chat 작업 및 Select AI RAG에서 SQL을 생성하는 데 가장 적합
OpenAI gpt-3.5-turbo (default)
gpt-4o
gpt-4o-mini
etc..
자연어 프롬프트, chat 작업 및 Select AI RAG에서 SQL을 생성하는 데 가장 적합
Cohere command (default)
command-nightly (experimental)
command-r
etc..
chat 작업에 가장 적합
Google gemini-1.5-flash (default)
gemini-1.5-pro
gemini-1.0-pro
etc..
자연어 프롬프트, chat 작업 및 Select AI RAG에서 SQL을 생성하는 데 가장 적합
Anthropic claude-3-5-sonnet-20240620 (default)
claude-3-opus-20240229
claude-3-sonnet-20240229
etc..
자연어 프롬프트, chat 작업 및 Select AI RAG에서 SQL을 생성하는 데 가장 적합
Hugging Face Mixtral-8x7B-Instruct-v0.1 (default)
Meta-Llama-3-70B-Instruct
Qwen1.5-1.8B
etc..
자연어 프롬프트, chat 작업 및 Select AI RAG에서 SQL을 생성하는 데 가장 적합

참고 : https://docs.oracle.com/en-us/iaas/autonomous-database-serverless/doc/select-ai-about.html

 

 

Select AI에서 사용가능한 명령어
runsql : 자연어 프롬프트에 대해 SQL 문을 생성하고 해당 SQL 쿼리를 실행하여 결과를 출력함(기본값)
narrate : 데이터베이스에서 실행된 SQL 쿼리 결과를 LLM에 전달하여 그 결과를 자연어로 설명함
*참고로 벡터 인덱스가 AI 프로파일에 지정되어 RAG가 활성화된 경우, 시스템은 지정된 트랜스포머 모델을 사용해 프롬프트로부터 벡터 임베딩을 생성하고, 벡터 저장소에 대해 의미 기반 유사도 검색을 수행함.
이후 벡터 저장소에서 검색된 콘텐츠를 사용자 프롬프트에 추가하고, 이를 LLM에 전달하여 해당 정보를 기반으로 응답을 생성함
showsql : 자연어 프롬프트에 대해 생성된 SQL 문만 표시함
explainsql : 생성된 SQL 문을 자연어로 설명함. 이 옵션은 생성된 SQL을 AI 제공자에게 보내고, AI가 이를 자연어 설명으로 변환하여 제공함
chat : 사용자 프롬프트를 그대로 LLM에 전달하여 응답을 생성함. 이 응답은 사용자에게 그대로 반환됨

 

 

테스트
api키 발급
먼저 openai에서 api키를 받아와야함
https://openai.com/index/openai-api/

 

 

사이트 접속 후 key 발급 

 

 

발급 받은 키 저장(이 창을 닫으면 더이상 키를 볼수없으니 개인 공간에 저장해둬야함)

 

 

발급된 키 확인 

 

 

23ai_selectai 용으로 발급받은 내 키는 아래와 같은 형태로 만들어져있음
sk-pr**-*****wA

 

 

api 키 발급 및 토큰도 구매해야함
나의경우 토큰이 없는 경우 제대로 동작하지 않아 10$만 충전해서 사용함
참고 : 
https://mixedcode.com/blog/detail?pid=6

 

 

LLM용 ACL 생성
*유저이름은 IMSI이고 OPENAI api를 사용함
*pdb에서 sys 유저로 수행

1
2
3
4
5
6
7
8
9
10
11
12
SQL>
BEGIN  
    DBMS_NETWORK_ACL_ADMIN.APPEND_HOST_ACE(
      host => 'api.openai.com',
      ace  => xs$ace_type(privilege_list => xs$name_list('http'),
                          principal_name => 'IMSI',
                          principal_type => xs_acl.ptype_db)
   );
END;
/
 
PL/SQL procedure successfully completed.

 

 

imsi 유저에 DBMS_CLOUD_AI 권한 부여

1
2
3
SQL> grant execute on dbms_cloud_ai to imsi;
 
Grant succeeded.

 

 

LLM용 자격증명 생성

*위에서 openai에서 발급 받은 api 키를 넣어줘야함
*pdb에서 sys 유저로 수행하라고 되어있었지만 에러발생해서 imsi 유저에서 생성함

1
2
3
4
5
6
7
8
9
SQL>
begin
dbms_cloud.create_credential (
            credential_name  => 'OPENAI_CRED',
            username         => 'IMSI',
            password         => 'sk-pr*******wA' --api key 삽입
            );
end;
/

 

 

참고. pdb의 sys유저에서 실행시 에러 발생함

1
2
3
4
5
6
*
ERROR at line 1:
ORA-06598: insufficient INHERIT PRIVILEGES privilege
ORA-06512: at "C##CLOUD$SERVICE.DBMS_CLOUD", line 1
ORA-06512: at line 2
Help: https://docs.oracle.com/error-help/db/ora-06598/

 

 

참고. credential 삭제 방법

1
2
3
4
5
6
SQL> 
begin
dbms_cloud.drop_credential (
            credential_name  => 'OPENAI_CRED');
end;
/

 

 

imsi 유저에 emp, dept 테이블 생성

1
2
3
SQL> @emp.sql
SQL> select * from emp;
SQL> select * from dept;

참고 : 오라클 EMP, DEPT table 생성 스크립트 ( https://positivemh.tistory.com/99 )

 

 

Select AI 프로필 생성
*pdb에서 sys 유저로 수행하라고 되어있었지만 에러발생해서 imsi 유저에서 생성함

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
SQL>
BEGIN
  DBMS_CLOUD_AI.create_profile(
      profile_name => 'TEST_OPENAI',
      attributes => '{"provider": "openai",
                      "comments": "true",
                      "model": "gpt-4o-mini",
                      "temperature": 0.2,
                      "max_tokens": 4096,
                      "conversation": "true",
                      "credential_name": "OPENAI_CRED",
                      "object_list": [{"owner": "IMSI", "name": "EMP"},
  {"owner": "IMSI", "name": "DEPT"}]}');
END;
/
 
PL/SQL procedure successfully completed.

옵션 설명 :
comments : Select AI가 LLM에 테이블 주석을 전송하여 SQL을 작성하는데 도움을 줄지 여부를 결정함
conversation : 프로필에 대화 기록이 활성화되어 있는지 여부를 나타냄
credential_name : LLM 제공자를 인증하는데 사용되는 자격 증명 이름임
object_list : 소유자와 SQL로 자연어 번역이 가능한 객체 이름을 지정하는 JSON 객체 배열임(스키마의 모든 테이블을 넣으려면 owner 만 넣으면됨)

model : 저렴한 gpt-4o-mini 모델을 사용함

 

 

참고. pdb의 sys유저에서 실행시 에러 발생함

1
2
3
4
5
6
*
ERROR at line 1:
ORA-06598: insufficient INHERIT PRIVILEGES privilege
ORA-06512: at "C##CLOUD$SERVICE.DBMS_CLOUD_AI", line 1
ORA-06512: at line 2
Help: https://docs.oracle.com/error-help/db/ora-06598/

 

 

참고. profile 삭제

1
2
3
SQL> exec dbms_cloud_ai.drop_profile(profile_name => 'TEST_OPENAI');
 
PL/SQL procedure successfully completed.

 

 

생성된 profile 확인(sys, system 유저 또는 dba권한 가진 유저로 실행)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
SQL> 
set lines 200 pages 1000
col profile_name for a20
col owner for a20
col description for a30
col created for a20
col last_modified for a20
select profile_id, profile_name, owner, description
, to_char(created, 'yyyy/mm/dd hh24:mi:ss') created, to_char(last_modified, 'yyyy/mm/dd hh24:mi:ss') last_modified 
from dba_cloud_ai_profiles;
 
PROFILE_ID PROFILE_NAME         OWNER                DESCRIPTION                    CREATED              LAST_MODIFIED
---------- -------------------- -------------------- ------------------------------ -------------------- --------------------
         2 TEST_OPENAI          IMSI                                                2025/04/02 23:24:51  2025/04/02 23:24:51

정상적으로 생성됨

 

 

생성된 profile 속성 확인(sys, system 유저 또는 dba권한 가진 유저로 실행)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
SQL> 
set lines 200 pages 1000
col profile_name for a20
col owner for a20
col attribute_name for a20
col attribute_value for a70
select profile_id, profile_name, owner, attribute_name, attribute_value
, to_char(last_modified, 'yyyy/mm/dd hh24:mi:ss') last_modified 
from dba_cloud_ai_profile_attributes
order by 2,3,4;
 
PROFILE_ID PROFILE_NAME         OWNER                ATTRIBUTE_NAME       ATTRIBUTE_VALUE                                                        LAST_MODIFIED
---------- -------------------- -------------------- -------------------- ---------------------------------------------------------------------- --------------------
         2 TEST_OPENAI          IMSI                 comments             true                                                                   2025/04/02 23:24:51
         2 TEST_OPENAI          IMSI                 conversation         true                                                                   2025/04/02 23:24:51
         2 TEST_OPENAI          IMSI                 credential_name      OPENAI_CRED                                                            2025/04/02 23:24:51
         2 TEST_OPENAI          IMSI                 max_tokens           4096                                                                   2025/04/02 23:24:51
         2 TEST_OPENAI          IMSI                 model                gpt-4o-mini                                                            2025/04/02 23:24:51
         2 TEST_OPENAI          IMSI                 object_list          [{"owner":"IMSI","name":"EMP"},{"owner":"IMSI","name":"DEPT"}]         2025/04/02 23:24:51
         2 TEST_OPENAI          IMSI                 provider             openai                                                                 2025/04/02 23:24:51
         2 TEST_OPENAI          IMSI                 temperature          0.2                                                                    2025/04/02 23:24:51
 
8 rows selected.

정상적으로 생성됨

 

 

현재 세션에서 AI 프로필을 설정(imsi 유저로 실행)

1
2
3
4
SQL> conn imsi/imsi@localhost:1521/oracle23pdb1
SQL> exec dbms_cloud_ai.set_profile (profile_name => 'TEST_OPENAI');
 
PL/SQL procedure successfully completed.

 

 

이제 Select AI를 사용할수 있음

 

 

Select AI에서 사용가능한 명령어
runsql : 자연어 프롬프트에 대해 SQL 문을 생성하고 해당 SQL 쿼리를 실행하여 결과를 출력함(기본값)
narrate : 데이터베이스에서 실행된 SQL 쿼리 결과를 LLM에 전달하여 그 결과를 자연어로 설명함
*참고로 벡터 인덱스가 AI 프로파일에 지정되어 RAG가 활성화된 경우, 시스템은 지정된 트랜스포머 모델을 사용해 프롬프트로부터 벡터 임베딩을 생성하고, 벡터 저장소에 대해 의미 기반 유사도 검색을 수행함.
이후 벡터 저장소에서 검색된 콘텐츠를 사용자 프롬프트에 추가하고, 이를 LLM에 전달하여 해당 정보를 기반으로 응답을 생성함
showsql : 자연어 프롬프트에 대해 생성된 SQL 문만 표시함
explainsql : 생성된 SQL 문을 자연어로 설명함. 이 옵션은 생성된 SQL을 AI 제공자에게 보내고, AI가 이를 자연어 설명으로 변환하여 제공함
chat : 사용자 프롬프트를 그대로 LLM에 전달하여 응답을 생성함. 이 응답은 사용자에게 그대로 반환됨

 

 

*참고로 select ai 실행시 에러가 발생한다면 LLM용 자격증명 생성 부분에서 api 키를 올바르게 넣었는지 확인해봐야함

1
2
3
4
5
6
7
8
SQL> select ai chat 'what is the oci?';
select ai chat 'what is the oci?'
*
ERROR at line 1:
ORA-20401: Authorization failed for URI - bearer://api.openai.com/v1/chat/completions
ORA-06512: at "C##CLOUD$SERVICE.DBMS_CLOUD", line 2060
ORA-06512: at "C##CLOUD$SERVICE.DBMS_CLOUD_AI", line 10137
ORA-06512: at line 1

 

 

*그리고 set_profile 명령을 수행하지 않고 select ai 쿼리를 수행하면 from 절을 입력하라고 표시됨

1
2
3
4
5
6
SQL> select ai runsql 'Who has the highest salary?';
select ai runsql 'Who has the highest salary?'
                 *
ERROR at line 1:
ORA-00923: FROM keyword not found where expected
Help: https://docs.oracle.com/error-help/db/ora-00923/

 

 

가장 높은 연봉을 가진 사람을 조회해봄
Who has the highest salary? 라는 질문으로 각 기능을 테스트해봄

 

 

Select AI runsql 기능 테스트

1
2
3
4
5
6
7
8
9
SQL> 
set timing on
select ai runsql 'Who has the highest salary?';
 
Employee_N     Salary
---------- ----------
KING             5000
 
Elapsed: 00:00:02.49

정상적으로 조회됨, 약 2.5초 소요됨

 

 

특정 테이블에서만 질문하려면 from 절을 넣어줘도 되는듯함

1
2
3
4
5
SQL> select ai runsql 'Who has the highest salary?' from emp;
 
Employee_N     Salary
---------- ----------
KING             5000

 

 

Select AI narrate 기능 테스트

1
2
3
4
5
6
7
SQL> select ai narrate 'Who has the highest salary?';
 
RESPONSE
-------------------------------------------------------------
The employee with the highest salary is KING, who earns 5000.
 
Elapsed: 00:00:02.05

쿼리에 대한 결과를 자연어로 잘 설명해줌

 

 

Select AI showsql 기능 테스트

1
2
3
4
5
6
7
8
9
SQL> select ai showsql 'Who has the highest salary?';
 
RESPONSE
---------------------------------------------------------------------
SELECT "E"."ENAME" AS "Employee_Name", "E"."SAL" AS "Salary"
FROM "IMSI"."EMP" "E"
WHERE "E"."SAL" = (SELECT MAX("E1"."SAL") FROM "IMSI"."EMP" "E1")
 
Elapsed: 00:00:02.05

쿼리가 잘 표시됨

 

 

Select AI explainsql 기능 테스트

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
SQL> select ai explainsql 'Who has the highest salary?';
 
RESPONSE
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Here is the SQL query to find the employee with the highest salary, using table aliases and easy-to-read column names, while considering case sensitivity:
 
```sql
SELECT "E"."ENAME" AS "Employee_Name", "E"."SAL" AS "Salary"
FROM "IMSI"."EMP" "E"
WHERE "E"."SAL" = (SELECT MAX("E1"."SAL") FROM "IMSI"."EMP" "E1");
```
 
### Explanation:
 
1. **SELECT Clause**:
   - `"E"."ENAME" AS "Employee_Name"`: This selects the employee's name from the `EMP` table and renames the column to "Employee_Name" for better readability.
   - `"E"."SAL" AS "Salary"`: This selects the salary of the employee and renames the column to "Salary".
 
2. **FROM Clause**:
   - `"IMSI"."EMP" "E"`: This specifies the table from which to retrieve the data. The table `EMP` is in the schema `IMSI`. The alias `"E"` is used for easier reference to this table in the query.
 
3. **WHERE Clause**:
   - The condition checks for the maximum salary:
     - `(SELECT MAX("E1"."SAL") FROM "IMSI"."EMP" "E1")`: This subquery retrieves the highest salary from the same `EMP` table. The alias `"E1"` is used for this subquery to differentiate it from the
outer query.
 
### Summary:
This query effectively retrieves the name and salary of the employee with the highest salary from the `EMP` table in the `IMSI` schema, ensuring that all identifiers are case-sensitive and properly en
closed in double quotes.
 
Elapsed: 00:00:07.90
 
번역
RESPONSE
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
다음은 대소문자를 구분하면서 테이블 별칭과 읽기 쉬운 열 이름을 사용하여 가장 높은 급여를 받는 직원을 찾는 SQL 쿼리입니다.
 
```sql
SELECT "E"."ENAME" AS "Employee_Name", "E"."SAL" AS "Salary"
FROM "IMSI"."EMP" "E"
WHERE "E"."SAL" = (SELECT MAX("E1"."SAL") FROM "IMSI"."EMP" "E1");
```
 
### 설명:
 
1. **SELECT 절**:
- `"E"."ENAME" AS "Employee_Name"`: `EMP` 테이블에서 직원 이름을 선택하고 가독성을 높이기 위해 열 이름을 "Employee_Name"으로 변경합니다.
- `"E"."SAL" AS "Salary"`: 직원의 급여를 선택하고 열 이름을 "Salary"로 변경합니다.
 
2. **FROM 절**:
- `"IMSI"."EMP" "E"`: 데이터를 검색할 테이블을 지정합니다. 테이블 `EMP`는 스키마 `IMSI`에 있습니다. 쿼리에서 이 테이블을 쉽게 참조할 수 있도록 별칭 `"E"`를 사용합니다.
 
3. **WHERE 절**:
- 이 조건은 최대 급여를 확인합니다.
- `(SELECT MAX("E1"."SAL") FROM "IMSI"."EMP" "E1")`: 이 하위 쿼리는 동일한 `EMP` 테이블에서 가장 높은 급여를 검색합니다. 이 하위 쿼리를 외부 쿼리와 구분하기 위해 별칭 `"E1"`을 사용합니다.
 
### 요약:
이 쿼리는 `IMSI` 스키마의 `EMP` 테이블에서 가장 높은 급여를 받는 직원의 이름과 급여를 효과적으로 검색합니다. 이때 모든 식별자는 대소문자를 구분하고 큰따옴표로 올바르게 묶어야 합니다.

쿼리와 함께 쿼리에 대한 마크업 형식(``, **등)으로 설명을 잘 해줌

 

 

Select AI chat 기능 테스트

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
SQL> select ai chat 'what is the oci?';
 
RESPONSE
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
OCI can refer to several different things depending on the context. Here are a few common meanings:
 
1. **Oracle Cloud Infrastructure (OCI)**: A cloud computing service offered by Oracle Corporation that provides a range of cloud services including computing, storage, networking, and database managem
ent.
 
2. **Open Container Initiative (OCI)**: An organization that aims to create open standards for container formats and runtimes, ensuring compatibility and interoperability among different container tec
hnologies.
 
3. **Overseas Citizenship of India (OCI)**: A form of permanent residency available to people of Indian origin and their spouses, allowing them to live and work in India indefinitely.
 
If you have a specific context in mind, please provide more details so I can give you a more precise answer!
 
번역
RESPONSE
-------------------------------------------------------------------------------------------------------------------------------------------
OCI는 맥락에 따라 여러 가지 다른 의미를 가질 수 있습니다. 다음은 몇 가지 일반적인 의미입니다.
 
1. **Oracle Cloud Infrastructure(OCI)**: Oracle Corporation에서 제공하는 클라우드 컴퓨팅 서비스로, 컴퓨팅, 스토리지, 네트워킹, 데이터베이스 관리를 포함한 다양한 클라우드 서비스를 제공합니다.
 
2. **Open Container Initiative(OCI)**: 컨테이너 형식 및 런타임에 대한 개방형 표준을 개발하여 다양한 컨테이너 기술 간의 호환성과 상호 운용성을 보장하는 것을 목표로 하는 조직입니다.
 
3. **Overseas Citizenship of India(OCI)**: 인도계와 그 배우자에게 제공되는 영주권으로, 인도에서 무기한 거주 및 근무가 가능합니다.
 
특정 맥락을 염두에 두고 계신다면 더 자세한 정보를 제공해 주시면 더 정확한 답변을 드릴 수 있습니다!

정상적으로 일반 질문에 대한 답변이 출력됨
일반적으로 chatgpt에서 질문하듯이 사용가능한 기능임

 

 

참고1. autotrace 결과 확인

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
SQL> set timing on
SQL> set autot on
SQL> exec dbms_cloud_ai.set_profile (profile_name => 'TEST_OPENAI');
 
PL/SQL procedure successfully completed.
 
SQL> select ai runsql 'Who has the highest salary?';
 
Employee_N     Salary
---------- ----------
KING             5000
 
Elapsed: 00:00:02.49
 
Execution Plan
----------------------------------------------------------
ERROR:
ORA-00923: FROM keyword not found where expected
Help: https://docs.oracle.com/error-help/db/ora-00923/
 
 
SP2-0612: Error generating AUTOTRACE EXPLAIN report
Help: https://docs.oracle.com/error-help/db/sp2-0612/
 
Statistics
----------------------------------------------------------
        986  recursive calls
         32  db block gets
        847  consistent gets
          0  physical reads
        728  redo size
        690  bytes sent via SQL*Net to client
        108  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          1  sorts (memory)
          0  sorts (disk)
          1  rows processed

autotrace는 from 절이 없어서 플랜이 나오지 않고 에러 발생함, 하지만 stat은 나옴

 

 

참고용2. xplan 결과 확인

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
SQL> alter session set statistics_level = all;
 
Session altered.
 
SQL> exec dbms_cloud_ai.set_profile (profile_name => 'TEST_OPENAI');
 
PL/SQL procedure successfully completed.
 
SQL> select ai runsql 'Please show me the name, department, and annual salary of the lowest paid person.';
 
Name       Department     Annual Salary
---------- -------------- -------------
SMITH      RESEARCH                9600
 
SQL> SELECT * FROM DBMS_XPLAN.DISPLAY_CURSOR(NULL, NULL, 'ADVANCED ALLSTATS LAST');
 
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SQL_ID  06749jpcc6kzm, child number 0
-------------------------------------
SELECT "E"."ENAME" AS "Name",         "D"."DNAME" AS "Department",
   ("E"."SAL" * 12) AS "Annual Salary" FROM "IMSI"."EMP" "E" JOIN
"IMSI"."DEPT" "D" ON "E"."DEPTNO" = "D"."DEPTNO" WHERE "E"."SAL" =
(SELECT MIN("SAL") FROM "IMSI"."EMP")
 
Plan hash value: 4175708089
 
----------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                    | Name    | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers |
----------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |         |      1 |        |       |     7 (100)|          |      1 |00:00:00.01 |      16 |
|   1 |  NESTED LOOPS                |         |      1 |      1 |    55 |     4   (0)| 00:00:01 |      1 |00:00:00.01 |      16 |
|   2 |   NESTED LOOPS               |         |      1 |      1 |    55 |     4   (0)| 00:00:01 |      1 |00:00:00.01 |      15 |
|*  3 |    TABLE ACCESS FULL         | EMP     |      1 |      1 |    33 |     3   (0)| 00:00:01 |      1 |00:00:00.01 |      14 |
|   4 |     SORT AGGREGATE           |         |      1 |      1 |    13 |            |          |      1 |00:00:00.01 |       7 |
|   5 |      TABLE ACCESS FULL       | EMP     |      1 |     14 |   182 |     3   (0)| 00:00:01 |     14 |00:00:00.01 |       7 |
|*  6 |    INDEX UNIQUE SCAN         | PK_DEPT |      1 |      1 |       |     0   (0)|          |      1 |00:00:00.01 |       1 |
|   7 |   TABLE ACCESS BY INDEX ROWID| DEPT    |      1 |      1 |    22 |     1   (0)| 00:00:01 |      1 |00:00:00.01 |       1 |
----------------------------------------------------------------------------------------------------------------------------------
 
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
 
   3 - SEL$58A6D7F6 / "E"@"SEL$1"
   4 - SEL$3
   5 - SEL$3        / "EMP"@"SEL$3"
   6 - SEL$58A6D7F6 / "D"@"SEL$1"
   7 - SEL$58A6D7F6 / "D"@"SEL$1"
 
Outline Data
-------------
 
  /*+
      BEGIN_OUTLINE_DATA
      IGNORE_OPTIM_EMBEDDED_HINTS
      OPTIMIZER_FEATURES_ENABLE('23.1.0')
      DB_VERSION('23.1.0')
      ALL_ROWS
      OUTLINE_LEAF(@"SEL$3")
      OUTLINE_LEAF(@"SEL$58A6D7F6")
      MERGE(@"SEL$1" >"SEL$2")
      OUTLINE(@"SEL$2")
      OUTLINE(@"SEL$1")
      FULL(@"SEL$58A6D7F6" "E"@"SEL$1")
      INDEX(@"SEL$58A6D7F6" "D"@"SEL$1" ("DEPT"."DEPTNO"))
      LEADING(@"SEL$58A6D7F6" "E"@"SEL$1" "D"@"SEL$1")
      USE_NL(@"SEL$58A6D7F6" "D"@"SEL$1")
      NLJ_BATCHING(@"SEL$58A6D7F6" "D"@"SEL$1")
      PUSH_SUBQ(@"SEL$3")
      FULL(@"SEL$3" "EMP"@"SEL$3")
      END_OUTLINE_DATA
  */
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   3 - filter("E"."SAL"=)
   6 - access("E"."DEPTNO"="D"."DEPTNO")
 
Column Projection Information (identified by operation id):
-----------------------------------------------------------
 
   1 - "E"."ENAME"[VARCHAR2,10], "E"."SAL"[NUMBER,22], "E"."DEPTNO"[NUMBER,22], "D"."DNAME"[VARCHAR2,14]
   2 - "E"."ENAME"[VARCHAR2,10], "E"."SAL"[NUMBER,22], "E"."DEPTNO"[NUMBER,22], "D".ROWID[ROWID,10]
   3 - "E"."ENAME"[VARCHAR2,10], "E"."SAL"[NUMBER,22], "E"."DEPTNO"[NUMBER,22]
   4 - (#keys=0) MIN("SAL")[22]
   5 - (rowset=256) "SAL"[NUMBER,22]
   6 - "D".ROWID[ROWID,10]
   7 - "D"."DNAME"[VARCHAR2,14]
 
Note
-----
   - dynamic statistics used: dynamic sampling (level=2)
   - this is an adaptive plan
 
Query Block Registry:
---------------------
 
  SEL$1 (PARSER)
  SEL$2 (PARSER)
    SEL$58A6D7F6 (VIEW MERGE SEL$2 ; SEL$1) [FINAL]
  SEL$3 (PARSER) [FINAL]
 
 
 
86 rows selected.

xplan 결과는 제대로 표시되지만 "select ai ~" 쿼리에 대한 실행계획이 아닌 select ai로 생성된 "SELECT "E"."ENAME" AS~" 쿼리에 대한 실행계획이 표시됨

 

 

참고용3. 한글 입력시 결과 이상

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
SQL> select ai runsql '가장 낮은 급여를 받는 사람의 이름과 부서, 연봉을 알려주세요.';
 
Employee Number Employee N Job Title Manager Number Hire Date     Salary Commission Department Number Department Nam Location
--------------- ---------- --------- -------------- --------- ---------- ---------- ----------------- -------------- -------------
           7839 KING       PRESIDENT                17-NOV-81       5000                           10 ACCOUNTING     NEW YORK
           7698 BLAKE      MANAGER             7839 01-MAY-81       2850                           30 SALES          CHICAGO
           7782 CLARK      MANAGER             7839 09-JUN-81       2450                           10 ACCOUNTING     NEW YORK
           7566 JONES      MANAGER             7839 02-APR-81       2975                           20 RESEARCH       DALLAS
           7788 SCOTT      ANALYST             7566 13-JUL-87       3000                           20 RESEARCH       DALLAS
           7902 FORD       ANALYST             7566 03-DEC-81       3000                           20 RESEARCH       DALLAS
           7369 SMITH      CLERK               7902 17-DEC-80        800                           20 RESEARCH       DALLAS
           7499 ALLEN      SALESMAN            7698 20-FEB-81       1600        300                30 SALES          CHICAGO
           7521 WARD       SALESMAN            7698 22-FEB-81       1250        500                30 SALES          CHICAGO
           7654 MARTIN     SALESMAN            7698 28-SEP-81       1250       1400                30 SALES          CHICAGO
           7844 TURNER     SALESMAN            7698 08-SEP-81       1500          0                30 SALES          CHICAGO
           7876 ADAMS      CLERK               7788 13-JUL-87       1100                           20 RESEARCH       DALLAS
           7900 JAMES      CLERK               7698 03-DEC-81        950                           30 SALES          CHICAGO
           7934 MILLER     CLERK               7782 23-JAN-82       1300                           10 ACCOUNTING     NEW YORK
 
14 rows selected.

한글로 질문했을때는 번역의 문제인지 전체 결과가 나와버림

 

 

영어로 질문시 정확하게 나옴

1
2
3
4
5
SQL> select ai runsql 'Please show me the name, department, and annual salary of the lowest paid person.';
 
Name       Department     Annual Salary
---------- -------------- -------------
SMITH      RESEARCH                9600

*SMITH의 salay가 800인데 *12(연봉)으로 계산해서 결과로 보여줌

 

 

참고4. v$sql에 select ai 구문 있는지 확인

1
2
3
4
5
6
7
8
9
10
11
SQL> select sql_id, sql_text from v$sql where sql_text like '%select ai%';
 
SQL_ID        SQL_TEXT
------------- ------------------------------------------------------------------
43rk68t8js1ry select sql_id, sql_text from v$sql where sql_text like '%select ai%'
 
SQL> select sql_id, sql_text from v$sql where sql_text like '%runsql%'
 
SQL_ID        SQL_TEXT
------------- ------------------------------------------------------------------
7nsb95zqacjfm select sql_id, sql_text from v$sql where sql_text like '%runsql%'

select ai 쿼리는 v$sql에 나오지 않음

 

 

참고5. select ai 에 이미 실행한 쿼리를 다시 수행하면 결과가 바로 출력됨
어딘가에 결과를 저장하고 있는듯함
저장소? 캐시?가 어디인지는 정확히 찾지못했음

 

 

결론 :
23.7버전부터 일반 DB(non-ADB)에서도 DBMS_CLOUD 및 Select AI 사용 가능함
DBMS_CLOUD_AI 패키지를 통한 LLM 연동 시 OpenAI, Azure, OCI 등 다양한 공급자를 지원함
runsql, narrate, showsql 명령은 약 2.5초 소요됨
explainsql 명령은 결과 내용이 길어서 그런지 약 8초 소요됨
chat 명령은 일반적으로 gpt에 질문하는 기능인데 굳이 sqlplus에서 실행을 자주하진 않을것 같음
잘쓰면 아주 유용하게 사용가능할듯함
현재로썬 외부(opanai 등)에 접속을 해서 llm 결과를 가져오는거라
실제 업무에서 사용하기는 힘들지 않을까 싶음. 외부 네트워크를 사용하지 않고 로컬 llm을 이용할수 있다면 더 유용하게 사용가능할듯함

 

 

참조 : 

2748362.1
https://docs.oracle.com/en/database/oracle/oracle-database/23/sutil/dbms_cloud-family-packages.html
https://docs.oracle.com/en/database/oracle/oracle-database/23/nfcoa/ru_23_7.html#GUID-104803-1
https://bryangrenn.blogspot.com/2025/03/23.7-Selectai.html?m=1
https://oracle-cloud.tistory.com/entry/Select-AI-%EC%BF%BC%EB%A6%AC-%EC%83%9D%EC%84%B1-%EA%B8%B0%EB%8A%A5-%EC%86%8C%EA%B0%9C
https://blog.cloudnueva.com/select-ai-is-not-a-toy
https://docs.oracle.com/en-us/iaas/autonomous-database-serverless/doc/select-ai-concepts.html
https://docs.oracle.com/en-us/iaas/autonomous-database-serverless/doc/select-ai-examples.html
https://docs.oracle.com/en-us/iaas/autonomous-database-serverless/doc/sql-generation-ai-autonomous.html
https://docs.oracle.com/en/cloud/paas/autonomous-database/dedicated/hsarg/index.html#articletitle