Java stored procedure running slow - java

I have a java web application that uses the next function to execute a stored procedure, it connects to SQL Server 2008:
Class.forName(sDriver_Reportes);
conn = DriverManager.getConnection(sDB_URL, sUSER, sPASS);
sQuery = "{call procGetResult(?)}";
proc = conn.prepareCall(sQuery);
proc.setString("pDate", sDate);
proc.execute();
rs = proc.getResultSet();
but it takes about 7 minutes to return the resultset, if I execute the sp it takes just 10 seconds to show the result.
I were looking for some similar case but only found post about parameter sniffing and connection pool but anyone seems to be like mi case because the sp is running fast, could you give me some info about where else to look about this issue.
Thank you in advance.

It seems to be a problem of SQL Server Parameter Sniffing. The first thing you need to check is the execution plan for your stored procedure.You can view it using the following icon in SQL Server Management Studio:
Now being exposed to the problem here are a few methods to address it:
Create SQL Server Stored Procedures using the WITH RECOMPILE Option
Use the SQL Server Hint OPTION (RECOMPILE) Use the SQL Server Hint
OPTION (OPTIMIZE FOR) Use Dummy Variables on SQL Server Stored
Procedures Disable SQL Server Parameter Sniffing at the Instance
Level Disable Parameter Sniffing for a Specific SQL Server Query
For implementation and better understanding you can refer the below link :
https://www.mssqltips.com/sqlservertip/3257/different-approaches-to-correct-sql-server-parameter-sniffing/

Related

Troubleshooting oracle database errors from cloud application

I am trying to troubleshoot an issue that presents as different database errors such as, ORA-01000: maximum open cursors exceeded or Unable to create DB Connection. I have reviewed the PLSQL to determine if cursors were left open and all are closed even if there is an error.
The java application and background are as follows:
The original application was a 3-tiered system:
GUI app. -> server app -> 11g Oracle database
The enhancement was to add an API service in a Pivotal Cloud Foundry (PCF) environment.
So this architecture was like this:
Close Function: GUI app -> Server App -> API service -> Database.
All other Functions: GUI app -> Server App -> Database.
This was put into production and run for a week without any database issues described above.
Then another enhancement was added in which the API Service communicates with several other services all in PCF in which 2 communicate with the same oracle database. Now during heavy volume we are getting these database errors.
It seems to me that the Oracle database cannot keep up with the requests from these additional services. But how can I demonstrate that. We have AppD configured for the servers but not the database. Are there queries that I can run in the prod env. that shows that these PCF applications are causing the issue? Or should I look in another area?
Thanks,
UPDATE
I looked at the legacy application and the result sets are closed. The other 3 PCF applications use Spring Boot to connect to the database. From my understanding, closing connections and result sets do not have to be explicitly closed. JDBCTemplate closes these connections/result sets. The PLSQL added has an additional cursor which is closed on success and exception.
UPDATE
I created a query that shows the total open cursor by sessionID
This is the query:
select b.sid, b.username, b.osuser, sum(a.value) total_opened_current_cursors
from sys.v_$statname c,
sys.v_$sesstat a,
sys.v_$session b
where a.statistic#=c.statistic# and
b.sid=a.sid and
c.name in ('opened cursors current') and
(b.username is not null or b.username <> '' )
group by b.sid, b.username, b.osuser
order by total_opened_current_cursors desc
Now, I need to link the sessionID with the application that has this session.
The osuser for the top ones is NULL.
Also, most of the sessions' status are INACTIVE
How to identify the application to the session?
Secondly, is the session is inactive, which I thought meant that no query is happening so why are there open cursors?
**UPDATE**
So, I wrote a query that returns the top 10 sessions with the highest open cursors
select *
FROM
(
select b.sid, b.username, b.osuser, b.status, sum(a.value) total_opened_current_cursors
from sys.v_$statname c,
sys.v_$sesstat a,
sys.v_$session b
where a.statistic#=c.statistic# and
b.sid=a.sid and
c.name in ('opened cursors current') and
(b.username is not null or b.username <> '' )
group by b.sid, b.username, b.osuser, b.status
order by total_opened_current_cursors desc
)
WHERE ROWNUM <= 10;
I found the SQL_TEXT that accounts for most of the open cursors...by far! (87%)
So, how do I find the query that calls this SQL?
There are at least 5 services that hit the database. Some of the services call PLSQL stored procedures some call raw SQL text. The query that accounts for the open cursors is listed as a SELECT statement. Does that mean it is NOT a stored procedure? Or can this SELECT be called within the stored procedures.
How do I find the connection that uses this session?

JAVA - How do I keep data stored into a internal DB (running SQL if possible)

My problem is that I don't even know what I am looking for ...
I created an app that should save data even without an internet connection and than update it into a External Server running SQL.I need to have my application to store the data into the pc itself
How do I accomplih that? What am I looking for? Derby?
in your code use
static final String DB_CONNECTION = "jdbc:mysql://127.0.0.1/dataBasename"

msSQL jdbc .. I connected to the server but how to connect to use a specific databaseName

Last time I used SQL with Java/Eclipse I had a SQL script linked to the Project.
This time, I connected to a different server using jdbc format (not localhost) and it connects correctly.
Now I need to get into this specific database named WInfo but I don't know how to do that.
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
c = DriverManager.getConnection("jdbc:sqlserver://serverName:1433/;user=UserName;password=******;");
Use below connection string:
c = DriverManager.getConnection("jdbc:sqlserver://SERVERNAME:PORTNO;databaseName=DATABASENAME;
user=MyUserName;password=*****");
OR
c = DriverManager.getConnection("jdbc:sqlserver://SERVERNAME:PORTNO;databaseName=DATABASENAME",
MyUserName, MyPassword);

Call to DataSource.getConnection not returning the expected connection

I have the following code:
Hashtable env1 = new Hashtable();
env1.put(javax.naming.Context.INITIAL_CONTEXT_FACTORY,"com.ibm.websphere.naming.WsnInitialContextFactory");
log.info("Executed step 1");
env1.put(javax.naming.Context.PROVIDER_URL, "iiop://myhost.com:9301");
log.info("Executed step 2");
Context ctx = new InitialContext(env1);
DataSource ds = (DataSource)ctx.lookup("jdbc/mydatasource");
log.info("Excecuted lookup ="+ds);
conn = ds.getConnection();
I have the previous code in an standalone application that is connecting to WAS 6.1.0.3 in order to retrieve a connection from the datasource. The code is very straighforward, and I have seen the same code working in a different environment, but in this case when I call getConnection I get an exception. The datasource is WAS has the proper authentication alias set and when the connection is tested it works OK from the WAS side, but the previous code won't work.
If I change this line: conn = ds.getConnection();
to this: conn = ds.getConnection("username","password");
Then the code will work! But that's not what I want since the connections in the datasource should already have the credentials set. I was initially thinking this was a Sybase problem, but it's also happening with Oracle, so would rather say I have a problem with WAS.
If you are curious about the exceptions, for Sybase I get:
java.sql.SQLException: JZ004: User name property missing in DriverManager.getConnection(..., Properties).DSRA0010E: SQL State = JZ004, Error Code = 0
at com.sybase.jdbc2.jdbc.ErrorMessage.raiseError(ErrorMessage.java:569)
at com.sybase.jdbc2.tds.LoginToken.<init>(LoginToken.java:128)
at com.sybase.jdbc2.tds.Tds.doLogin(Tds.java:506)
at com.sybase.jdbc2.tds.Tds.login(Tds.java:449)
at com.sybase.jdbc2.jdbc.SybConnection.tryLogin(SybConnection.java:254)
at com.sybase.jdbc2.jdbc.SybConnection.regularConnect(SybConnection.java:230)
at com.sybase.jdbc2.jdbc.SybConnection.<init>(SybConnection.java:200)
at com.sybase.jdbc2.jdbc.SybPooledConnection.<init>(SybPooledConnection.java:72)
at com.sybase.jdbc2.jdbc.SybConnectionPoolDataSource.createConnection(SybConnectionPoolDataSource.java:138)
at com.sybase.jdbc2.jdbc.SybDriver.connect(SybDriver.java:485)
at com.sybase.jdbc2.jdbc.SybDriver.connect(SybDriver.java:517)
at com.sybase.jdbc2.jdbc.SybDataSource.getConnection(SybDataSource.java:227)
at com.sybase.jdbc2.jdbc.SybConnectionPoolDataSource.getPooledConnection(SybConnectionPoolDataSource.java:74)
at com.ibm.ws.rsadapter.spi.InternalGenericDataStoreHelper$1.run(InternalGenericDataStoreHelper.java:897)
at com.ibm.ws.security.util.AccessController.doPrivileged(AccessController.java:118)
at com.ibm.ws.rsadapter.spi.InternalGenericDataStoreHelper.getPooledConnection(InternalGenericDataStoreHelper.java:892)
at com.ibm.ws.rsadapter.spi.WSRdbDataSource.getPooledConnection(WSRdbDataSource.java:1181)
at com.ibm.ws.rsadapter.spi.WSManagedConnectionFactoryImpl.createManagedConnection(WSManagedConnectionFactoryImpl.java:1047)
at com.ibm.ws.rsadapter.spi.WSDefaultConnectionManagerImpl.allocateConnection(WSDefaultConnectionManagerImpl.java:81)
at com.ibm.ws.rsadapter.jdbc.WSJdbcDataSource.getConnection(WSJdbcDataSource.java:431)
at com.ibm.ws.rsadapter.jdbc.WSJdbcDataSource.getConnection(WSJdbcDataSource.java:400)
And for Oracle I get this one:
java.sql.SQLException: invalid arguments in callDSRA0010E: SQL State = null, Error Code = 17,433
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:112)
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:146)
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:208)
at oracle.jdbc.driver.T4CConnection.logon(T4CConnection.java:236)
at oracle.jdbc.driver.PhysicalConnection.<init>(PhysicalConnection.java:420)
at oracle.jdbc.driver.T4CConnection.<init>(T4CConnection.java:165)
at oracle.jdbc.driver.T4CDriverExtension.getConnection(T4CDriverExtension.java:35)
at oracle.jdbc.driver.OracleDriver.connect(OracleDriver.java:801)
at oracle.jdbc.pool.OracleDataSource.getPhysicalConnection(OracleDataSource.java:297)
at oracle.jdbc.pool.OracleDataSource.getConnection(OracleDataSource.java:221)
at oracle.jdbc.pool.OracleConnectionPoolDataSource.getPhysicalConnection(OracleConnectionPoolDataSource.java:157)
at oracle.jdbc.pool.OracleConnectionPoolDataSource.getPooledConnection(OracleConnectionPoolDataSource.java:94)
at oracle.jdbc.pool.OracleConnectionPoolDataSource.getPooledConnection(OracleConnectionPoolDataSource.java:75)
at com.ibm.ws.rsadapter.spi.InternalGenericDataStoreHelper$1.run(InternalGenericDataStoreHelper.java:897)
at com.ibm.ws.security.util.AccessController.doPrivileged(AccessController.java:118)
at com.ibm.ws.rsadapter.spi.InternalGenericDataStoreHelper.getPooledConnection(InternalGenericDataStoreHelper.java:892)
at com.ibm.ws.rsadapter.spi.WSRdbDataSource.getPooledConnection(WSRdbDataSource.java:1181)
at com.ibm.ws.rsadapter.spi.WSManagedConnectionFactoryImpl.createManagedConnection(WSManagedConnectionFactoryImpl.java:1047)
at com.ibm.ws.rsadapter.spi.WSDefaultConnectionManagerImpl.allocateConnection(WSDefaultConnectionManagerImpl.java:81)
at com.ibm.ws.rsadapter.jdbc.WSJdbcDataSource.getConnection(WSJdbcDataSource.java:431)
at com.ibm.ws.rsadapter.jdbc.WSJdbcDataSource.getConnection(WSJdbcDataSource.java:400)
In both cases I won't the exception if I pass the credentials to the getConnection method
Thanks for your advice.
Short answer: external clients don't get to use the authentication alias data
Longer Answer:
From the WAS J2C connection factory documentation:
The alias that you configure for component-managed authentication does not apply to all clients that must access the secured resource. External Java clients with Java Naming and Directory Interface (JNDI) access can look up a Java 2 Connector (J2C) resource such as a data source or Java Message Service (JMS) queue. However, they are not permitted to take advantage of the component-managed authentication alias defined on the resource. This alias is the default value that is used when the getConnection() method does not specify any authentication data, like user and password, or a value for ConnectionSpec. If an external client needs to get a connection, it must assume responsibility for the authentication by passing it through arguments on the getConnection() call.
It's been a long time since I've done anything with WebSFEAR^H^H^H^Hphere, but it looks to me that you have a configuration problem. There was a special screen where you'd create credentials (user/pass) and later you'd apply those credentials to the created data source. It looks like that your configured data source hasn't got credentials applied.
Even after defining the user/password values as custom properties I found that the connections for Oracle weren't working. After many days, I just found that the development server is running an old WAS 6.1 version, the problem I'm having was fixed in WAS 6.1.0.5: PK32838: J2CA0046E WHEN USING USING CUSTOM PROP PASSWORD ON DATASOURECE
I tried my code in a different WAS server with an updated WAS fix pack level and... it worked without introducing a single change in the code or in the configuration. So the solution is to upgrade the WAS server.
Thanks.

How do I make my Java application identify itself to Oracle on connection?

When my application connects to an Oracle database I want to be able to see by looking at the active sessions in the database that it is connected. Currently it identifies itself as "JDBC Thin Client" because that's the driver that I'm using, but other Java based applications that I have are somehow able to set this value to something more meaningful, like "SQL Developer". I thought it was a property of the Connection or the OracleDataSource, but I've not managed to find one that does the trick. Is this possible? In case it matters, I'm using Java 1.5, with Oracle 10g and the 10g thin driver.
java.util.Properties props = new java.util.Properties();
props.setProperty("password","mypassword");
props.setProperty("user","myusername");
props.put("v$session.osuser", System.getProperty("user.name").toString());
props.put("v$session.machine", InetAddress.getLocalHost().getCanonicalHostName());
props.put("v$session.program", "My Program Name");
DriverManager.registerDriver (new oracle.jdbc.OracleDriver());
Connection conn=
DriverManager.getConnection("jdbc:oracle:thin:#myhostname:1521:mysid", props);
SQL>select username,osuser,program,machine
from v$session
where username = 'ROB';
USERNAME OSUSER PROGRAM MACHINE
--------- ----------- ------------------ -----------
ROB rmerkw My Program Name machine
At application level you can use the following methods to set client_info, module and action in v$session:
dbms_application_info.set_client_info
dbms_application_info.set_module
dbms_application_info.set_action
There is also an Oracle function:
dbms_application_info.set_client_info('Client Info');
which sets the ClientInfo column in v$session.
This might be useful if you only have access to the Connection rather than the underlying DataSource or DriverManager.
Since oracle jdbc 12.1 you can set some client-info values via jdbc api, i.e. you can do
connection.setClientInfo("OCSID.CLIENTID", "MyClientId");
for properties OCSID...
ACTION, CLIENTID, ECID, MODULE, SEQUENCE_NUMBER and DBOP
See https://docs.oracle.com/database/121/JJDBC/jdbcvers.htm#JJDBC29006
Setting PROGRAM doesn't work this way, you can do that as described in the accepted answer or somewhat easier by setting the System property "oracle.jdbc.v$session.program".
You need to define the connection property v$session.program in your data source, in such a way that that property will be added to each connection. How you do that depends on your data source implementation. The value you set the property to will appear in oracle's active session table.
Starting with 12.1 the setEndToEndMetrics is deprecated, you may use setClientInfo
see the documentation for 12.2 here
Here a snippet of the usage
// "conn" is an instance of java.sql.Connection:
conn.setClientInfo("OCSID.CLIENTID", "clientID");
conn.setClientInfo("OCSID.MODULE", "myModule");
conn.setClientInfo("OCSID.ACTION", "myAction");
You may see the setting in V$SESSION with this query of the relevant session
select MODULE, ACTION, CLIENT_IDENTIFIER from v$session where ...
but only after a next statement is executed with this connection. The call of setClientInfo triggers no extra roundtrip this information is passed whit the next call.
Note also that you must use the Oracle (unwrapped) conenction - Check this for reference.

Categories

Resources