I've been an Oracle DBA for a long time.
Over the years, I've solved a lot of database problems: ORA errors, performance issues, RAC, Data Guard, RMAN, ASM, storage problems and many others.
A lot of that knowledge never becomes a proper knowledge base. It stays in emails, tickets, chat conversations, documents, and sometimes, simply in the DBA's head.
So I Started Wondering:
What if I could give an AI access to that knowledge?
Not by fine-tuning a model.
Not by training an LLM.
Just by putting the knowledge into Oracle, converting it into vectors, searching it by meaning, and giving the relevant results to an LLM.
That became my first hands-on RAG experiment.
1. Starting with Oracle 26ai
I already had Oracle AI Database 26ai running inside Docker. I connected from PowerShell:
PS C:\Users\gokha> docker exec -it oracle26ai sqlplus dba_lab/<PASSWORD>@FREEPDB1
Connected to:
Oracle AI Database 26ai Free Release 23.26.2.0.0 - Develop, Learn, and Run for Free
So I had my database ready.
2. Creating a Small DBA Knowledge Base
I wanted to keep the first experiment simple. I created:
CREATE TABLE dba_knowledge (
id NUMBER PRIMARY KEY,
title VARCHAR2(200),
problem VARCHAR2(2000),
solution VARCHAR2(4000),
embedding VECTOR
);
Table created.
And the table structure:
SQL> DESC dba_knowledge;
Name Null? Type
----------------------------------------- -------- ----------------------------
ID NOT NULL NUMBER
TITLE VARCHAR2(200)
PROBLEM VARCHAR2(2000)
SOLUTION VARCHAR2(4000)
EMBEDDING VECTOR(*, *, DENSE)
I then added ten representative DBA problems:
Two examples of the INSERT statements:
-- For ORA-01555:
INSERT INTO dba_knowledge (id, title, problem, solution) VALUES (
1, 'ORA-01555 Snapshot Too Old',
'A long-running query fails with ORA-01555 during heavy transaction activity.',
'Check UNDO sizing and retention. Identify long-running queries and investigate undo generation. Verify whether required undo information is being overwritten.'
);
-- For High CPU:
INSERT INTO dba_knowledge (id, title, problem, solution) VALUES (
3, 'High CPU After Deployment',
'Database CPU increased significantly immediately after an application deployment.',
'Check AWR and ASH for Top SQL by DB Time. Compare execution plans before and after the deployment and investigate possible SQL plan regression.'
);
After inserting the ten cases, the knowledge base was ready.
3. Turning DBA Knowledge into Vectors
Now I needed to convert the text into something Oracle could search by meaning. I used my embedding model ALL_MINILM_L12_V2:
UPDATE dba_knowledge
SET embedding = VECTOR_EMBEDDING(
ALL_MINILM_L12_V2 USING title || ' ' || problem || ' ' || solution AS DATA
);
COMMIT;
10 rows updated. Commit complete.
Checking the vector dimensions:
SELECT id, title, VECTOR_DIMENSION_COUNT(embedding) AS dimensions FROM dba_knowledge ORDER BY id;
1 | ORA-01555 Snapshot Too Old | 384
2 | ORA-04031 Shared Pool Memory | 384
3 | High CPU After Deployment | 384
...
So my DBA knowledge had become a collection of 384-dimension vectors inside Oracle.
4. My First Semantic Search
Instead of searching for the exact title "High CPU After Deployment", I asked:
"My database CPU suddenly increased after a deployment. What should I check?"
SELECT id, title,
ROUND(VECTOR_DISTANCE(embedding, VECTOR_EMBEDDING(ALL_MINILM_L12_V2 USING 'My database CPU suddenly increased after a deployment. What should I check?' AS DATA), COSINE), 4) AS distance
FROM dba_knowledge ORDER BY distance FETCH FIRST 5 ROWS ONLY;
The closest match was High CPU After Deployment — 0.1937. I hadn't searched by exact words in the title; I searched by meaning!
5. Getting the Actual DBA Knowledge
Finding the title wasn't enough. I wanted the actual problem and solution, so I retrieved the top results:
Problem: Database CPU increased significantly immediately after an application deployment.
Solution: Check AWR and ASH for Top SQL by DB Time. Compare execution plans before and after deployment and investigate possible SQL plan regression.
Solution: Check database wait events, storage latency, I/O throughput, and AWR data.
At this point I had retrieval. But RAG needs one more thing: an LLM.
6. Installing Ollama
I decided to run the LLM locally. From Windows PowerShell:
PS C:\Users\gokha> winget install Ollama.Ollama
PS C:\Users\gokha> ollama --version
ollama version is 0.32.13
PS C:\Users\gokha> ollama pull phi3:mini
pulling 633fc5be925f: 100% ... 2.2 GB | success
PS C:\Users\gokha> ollama run phi3:mini
The local LLM was running.
7. Testing the Model
I started with simple questions:
PS C:\Users\gokha> ollama run phi3:mini
>>> What is Oracle Database?
Oracle Database is a multi-process, multi-threaded, client-server database management system produced and marketed by Oracle Corporation. It is a robust relational database system that supports various types of applications, including enterprise systems, web applications, and mobile applications. It provides a comprehensive set of tools for database design, development, administration, security, performance tuning, backup, and recovery.
Oracle Database is known for its high performance, scalability, and reliability. It offers a wide range of features, including advanced analytics, data warehousing, mobile data synchronization, and Big Data. It is also known for its enterprise-grade features, such as Real Application Clusters (RAC), which allows multiple instances to run concurrently on a single shared database.
Oracle Database is widely used in various industries, including finance, healthcare, retail, telecommunications, and manufacturing. It is considered a standard-bearer in the relational database industry and continues to evolve with new versions and features to keep up with changing demands.
Then I asked: "what is exadata ?" and "can exadata run on the AWS ?". The model answered all three. So far, so good.
Then I asked something much more relevant: "Explain ORA-01555 to an Oracle DBA in 3 sentences." The model gave an answer about undo, which sounded reasonable. But I wanted to test the model through its API.
8. My First LLM API Test
I initially tried curl.exe from PowerShell and got JSON escaping errors. So I switched to PowerShell's Invoke-RestMethod:
PS C:\Users\gokha> Invoke-RestMethod http://localhost:11434/api/generate `
>> -Method POST `
>> -ContentType "application/json" `
>> -Body '{"model":"phi3:mini","prompt":"Explain ORA-01555 in one sentence.","stream":false}'
model : phi3:mini
created_at : 2026-08-16T21:50:34.2149695Z
response : ORA-01555 is an error in Oracle databases indicating that a transaction cannot commit because it needs more blocks than are currently available in the buffer cache.
done : True
done_reason : stop
context : {32010, 29871, 13, 9544...}
total_duration : 3524793100
load_duration : 47453200
prompt_eval_count : 23
prompt_eval_duration : 117670000
eval_count : 35
eval_duration : 3349503000
That answer was wrong. And this was actually good news for my experiment because now I had something to compare against.
9. Connecting Docker to Ollama
Oracle was running inside Docker and Ollama on Windows host. I tested container connectivity using host.docker.internal:
docker exec -it oracle26ai bash
curl http://host.docker.internal:11434/api/generate -H "Content-Type: application/json" -d '{"model":"phi3:mini","prompt":"Say hello to Oracle DBA.","stream":false}'
"response":"Hello, Oracle DBA! How can I assist you today?"
10. One More Real DBA Problem: ACL
When I moved the call into Oracle itself, Oracle initially refused the HTTP request with:
I fixed it by allowing DBA_LAB to access the Ollama endpoint:
DBMS_NETWORK_ACL_ADMIN.APPEND_HOST_ACE(
host => 'host.docker.internal', lower_port => 11434, upper_port => 11434,
ace => XS$ACE_TYPE(privilege_list => XS$NAME_LIST('http'), principal_name => 'DBA_LAB', principal_type => XS_ACL.PTYPE_DB)
);
END;
/
Verified privilege HTTP for principal DBA_LAB. This made the experiment feel like a real DBA session.
11. Oracle Talks Directly to Ollama
Now I could use DBMS_VECTOR_CHAIN from Oracle:
SQL> SET SERVEROUTPUT ON SIZE UNLIMITED;
DECLARE
input CLOB;
output CLOB;
params CLOB;
BEGIN
input := 'Explain ORA-01555 to an Oracle DBA in one short paragraph.';
params := '{
"provider": "ollama",
"host": "local",
"url": "http://host.docker.internal:11434/api/generate",
"model": "phi3:mini"
}';
output := DBMS_VECTOR_CHAIN.UTL_TO_GENERATE_TEXT(input, JSON(params));
DBMS_OUTPUT.PUT_LINE(DBMS_LOB.SUBSTR(output, 32767, 1));
IF output IS NOT NULL THEN
DBMS_LOB.FREETEMPORARY(output);
END IF;
END;
/
SQL> SQL> 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
ORA-01555 is an error message that occurs in an Oracle database when the database cannot keep up with the demands of users for data. This error typically happens during periods of heavy data manipulation, such as during peak business hours, when the "ARCHIVELOG mode" is enabled, and there are insuinfficient disk space for the redo log files. The error indicates that the database is unable to write the redo records to the disk fast enough, leading to a potential loss of committed transactions. As a DBA, one should check the disk space and I/O subsystem performance, and consider tuning the database or increasing the I/O capacity to mitigate this issue.
PL/SQL procedure successfully completed.
Unfortunately, the answer was not good. The model hallucinated about ARCHIVELOG mode and disk space for redo log files.
This was the moment the reason for RAG became very clear. The LLM could generate an answer, but it didn't know — or didn't use — my DBA knowledge.
12. Now Let's Actually Build RAG
The final step was to combine the pieces:
I wrote the final PL/SQL block to: 1) Retrieve top 3 cases via VECTOR_DISTANCE(), 2) Build context, 3) Prompt model using ONLY provided knowledge.
13. The Final Test
I asked: "I am getting ORA-01555 Snapshot Too Old during a long-running query. What should I check first?"
SQL> SET SERVEROUTPUT ON SIZE UNLIMITED;
DECLARE
question CLOB;
context CLOB;
prompt CLOB;
answer CLOB;
params CLOB;
BEGIN
question := 'I am getting ORA-01555 Snapshot Too Old during a long-running query. What should I check first?';
/* 1. Find the most relevant DBA knowledge using Vector Search */
SELECT LISTAGG('Title: ' || title || CHR(10) || 'Problem: ' || problem || CHR(10) || 'Solution: ' || solution, CHR(10) || CHR(10)) WITHIN GROUP (ORDER BY distance)
INTO context
FROM (
SELECT title, problem, solution, VECTOR_DISTANCE(embedding, VECTOR_EMBEDDING(ALL_MINILM_L12_V2 USING question AS DATA), COSINE) AS distance
FROM dba_knowledge ORDER BY distance FETCH FIRST 3 ROWS ONLY
);
/* 2. Build the RAG prompt */
prompt := 'You are an Oracle DBA assistant.' || CHR(10) || CHR(10) ||
'Answer the following question using ONLY the DBA knowledge provided below.' || CHR(10) ||
'Do not use unrelated general knowledge.' || CHR(10) ||
'If the knowledge does not contain enough information, say so.' || CHR(10) || CHR(10) ||
'USER QUESTION:' || CHR(10) || question || CHR(10) || CHR(10) ||
'RETRIEVED DBA KNOWLEDGE:' || CHR(10) || context || CHR(10) || CHR(10) ||
'Give a concise, practical Oracle DBA troubleshooting answer.';
/* 3. Send the question + retrieved knowledge to Ollama */
params := '{"provider": "ollama", "host": "local", "url": "http://host.docker.internal:11434/api/generate", "model": "phi3:mini"}';
answer := DBMS_VECTOR_CHAIN.UTL_TO_GENERATE_TEXT(prompt, JSON(params));
DBMS_OUTPUT.PUT_LINE('================ RAG ANSWER ================');
DBMS_OUTPUT.PUT_LINE(DBMS_LOB.SUBSTR(answer, 32767, 1));
DBMS_OUTPUT.PUT_LINE('=============================================');
END;
/
SQL> SQL> 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
================ RAG ANSWER ================
First, check the UNDO sizing and retention settings. Ensure that undo information is not being overwritten too quickly during heavy transaction activity, which could cause ORA-01555.
=============================================
PL/SQL procedure successfully completed.
That was the moment the experiment clicked for me. The model didn't change. The model wasn't fine-tuned. I simply gave it the right context.
14. Before RAG vs. After RAG
Without RAG
Question → phi3:mini → General model knowledge → ❌ Wrong / unreliable answer (redo logs, ARCHIVELOG, I/O).
With RAG
Question → Embedding → Oracle Vector Search → Context → phi3:mini → ✅ UNDO sizing and retention.
The difference wasn't a smarter model. The difference was the knowledge supplied to the model.
15. What I Learned
16. The Interesting Part Isn't the Ten Records
Imagine replacing those ten rows with years of DBA emails, incident tickets, postmortems, runbooks, support cases, and internal documentation. When a DBA asks "Have we seen something like this before?", Oracle searches organizational history by meaning. That looks like institutional memory.
17. And I Didn't Fine-Tune Anything
I didn't train phi3:mini or modify the model. I changed the knowledge available to it. If I add another DBA incident tomorrow, I generate its embedding and store it in Oracle. The model stays the same. The memory grows.
Final Thoughts
I took a small collection of DBA troubleshooting knowledge, stored it in Oracle 26ai, converted it into vectors, searched it by meaning, and connected results to a local LLM running through Ollama.
Without my DBA knowledge, it gave me a bad answer. With the relevant knowledge retrieved from Oracle, the answer changed.
Maybe the next step isn't building an AI that knows everything. Maybe it's building an AI that can remember what the organization already knows.
