Eliminate most unnecessary changes to the database when values haven't been altered (reduces contention, and unnecessary constraint validation)

git-svn-id: http://scm.dspace.org/svn/repo/branches/dspace-1_5_x@2639 9c30dcfa-912a-0410-8fc2-9e0234be79fd
This commit is contained in:
Graham Triggs
2008-02-12 00:03:08 +00:00
parent 05253c036b
commit 95ce6e31bc
2 changed files with 102 additions and 19 deletions

View File

@@ -632,24 +632,34 @@ public class DatabaseManager
StringBuffer sql = new StringBuffer().append("update ").append(table)
.append(" set ");
List columns = new ArrayList();
ColumnInfo pk = getPrimaryKeyColumnInfo(table);
ColumnInfo[] info = getNonPrimaryKeyColumns(table);
String seperator = "";
for (int i = 0; i < info.length; i++)
{
sql.append((i == 0) ? "" : ", ").append(info[i].getName()).append(
" = ?");
// Only update this column if it has changed
if (row.hasColumnChanged(info[i].getName()))
{
sql.append(seperator).append(info[i].getName()).append(" = ?");
columns.add(info[i]);
seperator = ", ";
}
}
// Only execute the update if there is anything to update
if (columns.size() > 0)
{
sql.append(" where ").append(pk.getName()).append(" = ?");
List columns = new ArrayList();
columns.addAll(Arrays.asList(info));
columns.add(pk);
return execute(context.getDBConnection(), sql.toString(), columns, row);
}
return 1;
}
/**
* Delete row from the RDBMS.
*
@@ -1107,6 +1117,8 @@ public class DatabaseManager
}
}
// Now that we've prepped the TableRow, reset the flags so that we can detect which columns have changed
row.resetChanged();
return row;
}

View File

@@ -67,6 +67,8 @@ public class TableRow
*/
private Map data = new HashMap();
private Map changed = new HashMap();
/**
* Constructor
*
@@ -82,6 +84,7 @@ public class TableRow
{
this.table = table;
nullColumns(columns);
resetChanged(columns);
}
/**
@@ -107,6 +110,18 @@ public class TableRow
return data.get(canonicalize(column)) != null;
}
/**
* Return true if this row contains this column and the value has been updated.
*
* @param column
* The column name (case-insensitive)
* @return True if this row contains a column with this name.
*/
public boolean hasColumnChanged(String column)
{
return changed.get(canonicalize(column)) == Boolean.TRUE;
}
/**
* Return true if the column is an SQL NULL.
*
@@ -387,15 +402,26 @@ public class TableRow
throw new IllegalArgumentException("No such column " + column);
}
String canonName = canonicalize(column);
if ("oracle".equals(ConfigurationManager.getProperty("db.name")))
{
// if oracle, use 1 or 0 for true/false
data.put(canonicalize(column), b ? new Integer(1) : new Integer(0));
Integer value = b ? new Integer(1) : new Integer(0);
if (!value.equals(data.get(canonName)))
{
data.put(canonName, value);
changed.put(canonName, Boolean.TRUE);
}
}
else
{
// default to postgres true/false
data.put(canonicalize(column), b ? Boolean.TRUE : Boolean.FALSE);
Boolean value = b ? Boolean.TRUE : Boolean.FALSE;
if (!value.equals(data.get(canonName)))
{
data.put(canonName, value);
changed.put(canonName, Boolean.TRUE);
}
}
}
@@ -416,7 +442,13 @@ public class TableRow
throw new IllegalArgumentException("No such column " + column);
}
data.put(canonicalize(column), (s == null) ? NULL_OBJECT : s);
String canonName = canonicalize(column);
Object value = (s == null) ? NULL_OBJECT : s;
if (!value.equals(data.get(canonName)))
{
data.put(canonName, value);
changed.put(canonName, Boolean.TRUE);
}
}
/**
@@ -436,7 +468,13 @@ public class TableRow
throw new IllegalArgumentException("No such column " + column);
}
data.put(canonicalize(column), new Integer(i));
String canonName = canonicalize(column);
Integer value = new Integer(i);
if (!value.equals(data.get(canonName)))
{
data.put(canonName, value);
changed.put(canonName, Boolean.TRUE);
}
}
/**
@@ -456,7 +494,13 @@ public class TableRow
throw new IllegalArgumentException("No such column " + column);
}
data.put(canonicalize(column), new Long(l));
String canonName = canonicalize(column);
Long value = new Long(l);
if (!value.equals(data.get(canonName)))
{
data.put(canonName, value);
changed.put(canonName, Boolean.TRUE);
}
}
/**
@@ -477,14 +521,13 @@ public class TableRow
throw new IllegalArgumentException("No such column " + column);
}
if (d == null)
String canonName = canonicalize(column);
Object value = (d == null) ? NULL_OBJECT : d;
if (!value.equals(data.get(canonName)))
{
setColumnNull(canonicalize(column));
return;
data.put(canonName, value);
changed.put(canonName, Boolean.TRUE);
}
data.put(canonicalize(column), d);
}
////////////////////////////////////////
@@ -583,6 +626,29 @@ public class TableRow
}
}
private void resetChanged(List columns)
{
for (Iterator iterator = columns.iterator(); iterator.hasNext();)
{
changed.put(canonicalize((String) iterator.next()), Boolean.FALSE);
}
}
/**
* package private method to reset the flags of which columns have been updated
* This is used by the database manager after it has finished processing the contents
* of a resultset, so that it can update only columns that have been updated.
* Note that this method does not reset the values themselves, only the flags,
* and should not be considered safe to call from anywhere other than the DatabaseManager.
*/
void resetChanged()
{
for (Iterator iterator = changed.keySet().iterator(); iterator.hasNext();)
{
changed.put(canonicalize((String) iterator.next()), Boolean.FALSE);
}
}
/**
* Internal method to set column to null. The public method ensures that
* column actually exists.
@@ -591,6 +657,11 @@ public class TableRow
*/
private void setColumnNullInternal(String column)
{
data.put(canonicalize(column), NULL_OBJECT);
String canonName = canonicalize(column);
if (data.get(canonName) != NULL_OBJECT)
{
data.put(canonName, NULL_OBJECT);
changed.put(canonName, Boolean.TRUE);
}
}
}