Why is H2 slow when updating Blobs? - java

I need some sort of persistance componnent to store id(long) and value(object) for my Java application.
All The cacheing systems I looked at where not persistant enough(If the process died the cache would erase itself) or slow
I tried to use Embedded DataBases like Derby and HSQLDB but they where not as fast as H2 as SELECT and INSERT.
For some reason the UPDATE query takes 1-2 seconds for one row if I Update a row with Blob.
Does anyone know why is it this slow?
Queries:
CREATE TABLE ENTITIES(ID BIGINT PRIMARY KEY, DATA BLOB)
INSERT INTO ENTITIES(DATA, ID) VALUES(?, ?)
UPDATE ENTITIES SET DATA = ? WHERE ID = ?
I am using JDBC with PreparedStatement
Edit:
The connection string is:
jdbc:h2:C:\temp\h2db;FILE_LOCK=NO;
I tried to add CACHE_SIZE=102400 and PAGE_SIZE=209715200 but it didn't help

Related

Automate partition creation in databases

Is there a way to create partitions from Java spring code, in case any database is missing partition?
In the DB we write query like this -
ALTER TABLE <table_name> ADD PARTITION (PARTITION p1 VALUES LESS THAN (time));
You can fire any random SQL query in spring application using jdbcTemplate object.
jdbcTemplate.execute("DROP TABLE customers IF EXISTS");

Create table with longvarchar consistently in Hsqldb and Oracle

In my project, we use hsqldb for running unit test cases and oracle in production. Liquibase is used to run queries on environments. I have an issue with creating table with datatype LONGVARCHAR. I am already using this statement to use oracle syntax in hsqldb.
SET DATABASE SQL SYNTAX ORA TRUE
When I try to create table in hsqldb, this query seem to work.
CREATE TABLE A (DATA LONGVARCHAR);
And when I try to create table in oracle, the following works.
CREATE TABLE A (DATA LONG VARCHAR);
How can I write a homogeneous query which can work for both database servers.
Use a CLOB
CREATE TABLE A (DATA CLOB);

Can I SELECT with LAST_INSERT_ID() after INSERT Batch without any cares?

I'm asking myself if it is possible to SELECT with LAST_INSERT_ID() in WHERE Clause after an batch of INSERTs without getting corrupt data in the tables? I'm thinking of the scenario that multiple users doing the same stuff at the same time. I develop an JSF Application in which this scenario can be possible.
In hard Code my SELECT after INSERTs looks like this:
preparedstatement.addBatch(
"INSERT INTO table1(all the FIELDS)"
+ "VALUES(null, ...);"
);
preparedstatement.addBatch(
"INSERT INTO table2(all the FIELDS)"
+ "VALUES(null, LAST_INSERT_ID(), ...);"
);
preparedstatement = connect.prepareStatement(
"SELECT id FROM table3 WHERE id = LAST_INSERT_ID();"
);
preparedstatement.executeBatch();
resultSet = preparedstatement.executeQuery();
Get I problems with this implementation or is there an better way?
Best Regards
You should be fine, quoting MySQL's documentation:
The ID that was generated is maintained in the server on a
per-connection basis. This means that the value returned by the
function to a given client is the first AUTO_INCREMENT value generated
for most recent statement affecting an AUTO_INCREMENT column by that
client. This value cannot be affected by other clients, even if they
generate AUTO_INCREMENT values of their own. This behavior ensures
that each client can retrieve its own ID without concern for the
activity of other clients, and without the need for locks or
transactions.
MySQL Last_insert_id

Migrate data from old MySQL database

I recently rewrote a Java EE web application (running on a MySQL database) to Rails 3.1. The problem now is that the database model of the new application is not the same as the old one because I added, removed and renamed some attributes. The database table names are also different.
Is there a way of migrating this data? The only way I can imagine to do this is writing a stored procedure with many ALTER TABLE and CREATE TABLE statements to update the database to the new model.
Thanks in advanced.
Solution:
I finally used INSERT..SELECT statements in a mysql stored procedure to migrate the data. INSERT INTO new_schema.new_table SELECT FROM old_schema.old_table. I am now considering making a Rake task to call that procedure and doing other stuff.
The only way is to write a script that take the data from the old db and insert thme in the new db. Or you can in some way to connect to the two databases and then make some select and insert query, something like
insert into new_db.table as select old_db.table.field1, ....
or
insert into new_db.table (field_1, field_2) values (select old_db.table.field_1, ...)
In any way, is a manual process, also if can be automated to some extend with a script
Instead of a Store procedure you can try with rails and some sql within the rails console using the information_schema of mysql
sql = ActiveRecord::Base.connection()
old_tables = sql.execute "select table_name from information_schema.tables where table_schema = your_old_schema"
res.each do | old_table|
old_fields = sql.execute "select distinct column_name, data_type from information_schema.columns where table_name='#{old_table}' and table_schema='your_old_schema'"
new_fields = sql.execute "select distinct column_name, data_type from information_schema.columns where table_name='#{old_table}' and table_schema='your_new_schema'"
#compare fields and so on...
end

Can't update Oracle IOT table with jbdc updateRow method

I have Oracle 10gR2 database with IOT table within:
create table countries (
id number primary key,
name varchar2(30) not null enable
) organization index;
I try to update table values with this Java (version 1.6) code:
Statement stmt = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_UPDATABLE);
ResultSet src = stmt.executeQuery("select id, name from countries");
src.next();
src.updateString("name", "__test__");
src.updateRow();
But updateRow throws SQLException (ORA-01410: invalid ROWID). If I try to update a heap (ordinary) table - all works.
I have use this code with different versions of oracle drivers (from here http://www.oracle.com/technology/software/tech/java/sqlj_jdbc/htdocs/jdbc_10201.html)
After some research I have detected that IOT and HEAP table have different format of rowids:
IOT example *BAJzKgwCwRb+
HEAP example AAAbgVAAJAAMyr8AAA
But I still don't know how to solve this problem. Are you have any ideas?
Can you get the results of an extended SQL trace of your query to see what JDBC's doing under the covers? I suspect it's attempting to do
UPDATE COUNTRIES SET NAME = '__TEST__' WHERE ROWID = :rowid_fetched
and ROWID means something totally different in Oracle IOT's; it's not the immutable address of a row, but a guess as to the path to the row.
My recommendation as to how to do this is to propagate a system-generated timestamp field onto all of your tables, and use that for concurrency control rather than declaring an updatable recordset -- which will take and hold locks for every record in the recordset.
Then your application would fetch the rowset as normal, but issue statements like:
UPDATE COUNTRIES SET NAME = '__TEST__' WHERE MOD_TS = :mod_ts_fetched
to give stateless optimistic locking.
Looks like your table does not really need to be IOT. I would suggest you recreate it as a normal table and add index on both ID and name. Same performance, same logic, no ROWID problem.

Categories

Resources