How to view Execution Plans for Oracle Database in Java - java

With SQL Plus for Oracle Database, I can call
SET autotrace on
and then see Execution Plan, statistics, etc.
The problem is that I want access to information about the Execution Plan and statistics in my Java program. I typically have done something like this to execute a sql statement,
Connection connection = //INITIALIZE HERE;
Statement getColumn = connection.createStatement();
ResultSet results = getColumn.executeQuery("INSERT SQL QUERY HERE");
while(results.next())
{
//view results
}
Is there a way I can get the Execution Plan and Statistics? Thanks.

You can query the V$SQL_PLAN table to get the explain plain. Alternatively you can query the PLAN_TABLE, you can see more details on this HERE.

Related

Error or wrong type of code while creating connection & execute SQL query statements using mysql in java

I'm using MySQL 5.7 with Java in Eclipse, and the connection statement below code below is causing an error when I try to connect:
try
{
//1. Get a connection to database
jdbc:mysql://localhost:3306/databaseName?autoReconnect=true;useSSL=false;
// 2. Create a statement
Statement myStmt=myConn.createStatement();
// 3. Execute SQL query
ResultSet myRs=myStmt.executeQuery("select * from employee");
//4. Process the result set
while(myRs.next())
{
System.out.println(myRs.getString("last_name")+","+myRs.getString("first_name"));
}
}
catch(Exception exc){
exc.printStackTrace();
}
First things first.
Code will only be used to validate the error. So you must paste the error fired by your program.
Since we don't have enough information to the problem, I will just cover basic troubleshooting.
Basic trouble shooting:
Do you have the driver? if not, you can download it here.
Next, Do you have the driver on your project class path? If not yet, you must add it. see how here
Did you load the driver to the program? if not, Class.forName("com.mysql.jdbc.Driver"); // Load Driver like that before doing anything.
Did you establish the connection? if not, Connection con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/DATABASE","USERNAME","PASSWORD");//3306 or port number depends on you config, same with DATABASE, USERNAME, PASSWORD
After the connection were established, so you should create a statement object like Statement s = con.createStatement(); // Create Statement. This will be used to execute sql commands.
finally, you can execute the commands like s.execute("select * from employee"); // Execute Query NOTE that s here is the variable created on number 5.
If all of the above were properly done but still gets an error, check if your have the database server running. In you case, mysql. Make sure there were not other installation of mysql prior to your current mysql. Sometimes, it will mess up your database. Troubleshooting your mysql, see mysql official doc here
While possible error is the datatype of mysql to your java code or getting a column that does not exist on your query or worse the column does not exist on your table.
Hope that help you and other who needs it.

Quartz scheduler not executing the SQL Query in a dropwizard application

I've an application created using dropwizard framework where I've registered a quartz-scheduler job scheduled to run after every specified duration. This job fires a SQL query to SQL Server DB and iterates the ResultSet and sets the data to a POJO class which is later pushed to a queue.
The SQL query has UNION joining multiple tables which fetches the data for the records modified in a delta time using the last_modified_time column of the related table in where clause. DB jar included in pom.xml is sqljdbc-4.4.0 and quartz version is 2.2.1
The query looks like this:
SELECT
u.last_modified_date,
u.account_id,
u.user_id,
ud.is_active
FROM user u WITH (NOLOCK)
JOIN user_details ud with (NOLOCK) ON u.account_id = ud.account_id AND u.user_id = ud.user_id
WHERE u.last_modifed_date > ? AND ud.last_modifed_date <= ?
UNION
SELECT
u.last_modified_date,
u.account_id,
u.user_id,
ud.is_active
FROM user u WITH (NOLOCK)
JOIN user_details ud with (NOLOCK) ON u.account_id = ud.account_id AND u.user_id = ud.user_id
JOIN user_registration_details urd WITH (NOLOCK) ON urd.account_id = u.account_id AND urd.user_id = u.user_id AND urd.reg_id = ud.reg_id
WHERE urd.last_modifed_date > ? AND urd.last_modifed_date <= ?
This query is called by simple connection statement and resultset like this
final ManagedDataSource datasource configuration.getDatabase().build(environment.metrics(), "sql");
// configuration is the configuration class in a drop wizard application and configuration.getDatabase() returns
// the DataSourceFactory with all credentials like user, password and url set into it
try (Connection conn = dataSource.getConnection()) {
int resultSetType = SQLServerResultSet.TYPE_SS_SERVER_CURSOR_FORWARD_ONLY;
int resultSetConcurrency = ResultSet.CONCUR_READ_ONLY;
LOGGER.info("Starting execution: ");
try (PreparedStatement pstmt = conn.prepareStatement(getQuery(), resultSetType,resultSetConcurrency))
{
setQueryParameters(pstmt);
try (ResultSet rs = pstmt.executeQuery();)
{
//process results
}
}
} catch (SQLException | IOException ex) {
LOGGER.error(“Error occurred “ + ex);
}
LOGGER.info("Completed execution: ");
In a simple execution, it prints the logs "Starting execution" and then processes the records and prints "completed execution". But sometimes during the execution, it's printing the logs "Starting execution" and "completed execution" but this query is not actually fired to the SQL DB.
As I didn't get the records which I modified in that delta time, I put the profiler to check if the query is actually fired and didn't found this query firing to the DB. Also, I've tried adding log4jdbc library http://code.google.com/p/log4jdbc/wiki/FAQ to print the query to the logs but no logs were printed for this query.
with (NOLOCK) is not MySQL syntax. Look at the settings in the wizard and see if you have specified the correct RDBMS engine. In particular, it sounds like SQL Server syntax.
The equivalent may involve setting the TRANSACTION ISOLATION LEVEL to something like READ UNCOMMITTED.
I turned the SQL Profiler on this query and filtered it for my server to check if the query was actually hitting the DB from my application and found that the profiler could only find it rarely hitting the DB. So, I thought there might be some caching happening at mybatis level. Then I added more logs and performed debug analysis on mybatis by enabling all kind of logging and to check if there are any caching at local level or second level cache mybatis configuration but that wasn't the cause.
Then I used spy jdbc driver log4jdbc driver to log all the queries, parameters and all db information requests at db level.
My organization is using Spunk application to display logs from all the applications deployed to the different host servers. While checking the logs in splunk, I observed the same query was printed twice in the logs but when I noticed deeply it was printing one from my instance and another execution from the different instance deployed on some other server. I logged in to that server and found the same application deployed over there not updated since months. It was found to be multiple application instances running in the same environment but on two different servers and there is no way I could figure out that an application was deployed on multiple hosts.
Thank you #halfer for all the help and bounty.

using MySQL event scheduler with Java

I am trying to create events using Java code with hibernate. I verified my syntax for CREATE EVENT in MySQL Workbench, and I verified my Java code with a simple UPDATE query. But when I am trying to use both it just doesn't work. I am not getting any error message, just that 0 rows were affected. My code is as follows:
String sql = "CREATE EVENT IF NOT EXISTS test_event ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 20 SECOND ON COMPLETION PRESERVE ENABLE DO UPDATE my_table SET last_error_message='my test' WHERE ID=17;";
session.beginTransaction();
SQLQuery query = session.createSQLQuery(sql);
int result = query.executeUpdate();
session.getTransaction().commit();
....
session.close();
thanks a lot
How do you know if any new events were created? You can try
show events from <SCHEME_NAME>;
This will show all the events that are registered to the given schema.try printing the session\statement warning stack...
Get jdbc connection from your session: How to get jdbc connection from hibernate session?
Use JDBC to execute DDL
...
Statement stmt = null;
try {
stmt = conn.createStatement();
stmt.executeUpdate(sql);
} catch (SQLException e) {
// ...
} finally {
// close stmt
}
...
First, you need to make sure your database is prepared to execute an event. for that, you need to run the following command.
SHOW PROCESSLIST;
MySQL uses a special thread called event schedule thread to execute all scheduled events.
if you see your process list like the above picture. you need to run the below command to enable MySQL event execution.
SET GLOBAL event_scheduler = ON;
Then when you execute the "SHOW PROCESSLIST;" command you will see the below list which shows the specific thread for event execution in MySQL.
Now you can create your event using any MySQL client interface.

Fetching data from Oracle database does not work first time

We are trying to fetch data from Oracle DB using a PreparedStatement. It keeps fetching zero records while the same runs and fetches data when run from PL/SQL developer.
We found the root cause while trying to debug. While debugging the code fetched the two records properly.
We did a temporary fix by placing this piece of code.
ResultSet rs = ps.executeQuery();
while(!rs.hasNext()){
ps.executeQuery();}
This works. But this is not the best solution since it results in an unwanted DB hit.It clearly looks like a time issue. We also explicitly committed earlier transactions since they can affect the result of this query.
What could be causing this. What's the best way to solve this?
The method is quite big: I'll just post some parts here:
private static boolean loadCommission(Member member){
Connection conn = getConnection("schema1"); //obtained through connection pool
//insertion into table
conn.close();
Conn conn2 = getConnection("schema2"); //obtained through connection pool
PreparedStatement ps = conn2.prepareStatement(sql);
//this sql combines data from schema1
// and 2 with DB links
ResultSet rs = ps.executeQuery();
//business logic
conn2.close();
return true;
}
Thanks
We tried a few more things yesterday. We replaced the second connection code with direct jdbc connection like so
Connection conn = DriverManager.getConnection(URL, USER, PASS);
This too works. Now we are not sure if the delay is in getting connection from pool or in completing previous transaction like we thought earlier.
If your query selects from a materialized view, then there may be some elapsed time before it will yield results (as materialized views do not necessarily refresh instantly after a commit, depending upon how they've been created).
If this is the case, then you can resolve the problem by either selecting directly from the base table (or equivalent non-materialized views), or forcing the materialized view to refresh.

The Following simple query does not complete. Prepared Statement

i have the following query:
String updatequery = "UPDATE tbl_page SET linkCount = ?, pageProcessed = 1 WHERE pageUrl =?";
PreparedStatement updatestmt = kon.prepareStatement(updatequery);
updatestmt.clearParameters();
//updatestmt.setQueryTimeout(10);
updatestmt.setInt(1, linkCount);
updatestmt.setString(2, urlLink);
updatestmt.executeUpdate();
When i set the query timeout for 10 seconds it will catch an exception the query timed out. but when i dont it goes on waiting. Whats wrong with the query? pageUrl column is the Primary Key with varchar(900)
I know something might be wrong with the prepared statement because when i run this query in MS SQl Server Management Studio ('?' replaced with its value) it works fine.
Am i missing something in Java or MSSQL?
Since the code looks just fine, this could be an issue at database side. May be someone else has blocked the row by updating it and not doing a commit/rollback (most possibly from you MS-SQL Server Management studio !). You could look for locks owned by other processes for the same record so that you can be sure that this is not a database issue.
Create an index on pageUrl:
create index tbl_page_pageUrl_index on tbl_page(pageUrl);
That will allow speedy access to the rows you want to update.
Without this index, the database must do a full table scan, and when combined with an update command, if likely to lead to lock contention and possibly even deadlocks, depending on your locking options.

Categories

Resources