В Java, как PreparedStatement работает для следующего запроса - PullRequest
1 голос
/ 14 сентября 2010

У меня есть запрос, подобный следующему, и мне было интересно, какой SQL создается путем пакетной обработки PreparedStatement.

INSERT INTO table1 (id, version, data)
  VALUES (?, ?, ?)
  ON DUPLICATE KEY UPDATE 
    table1.data = IF(table1.version > table2.version, table1.data, table2.data),
    table1.version = IF(table1.version > table2.version, table1.version, table2.version)

Вопрос в том, разрешит ли он эту копию всей строки SQL длякаждая строка в пакете, или она будет делать что-то вроде:

INSERT INTO table1 (id, version, data)
  VALUES (a1, b1, c1), (a2, b2, c2), (a3, b3, c3), ...
  ON DUPLICATE KEY UPDATE 
    table1.data = IF(table1.version > table2.version, table1.data, table2.data),
    table1.version = IF(table1.version > table2.version, table1.version, table2.version)

Если нет, как это влияет на производительность и как я могу написать это таким образом, чтобы я мог пакетировать многие из этих INSERT..UPDATEоператоры, использующие PreparedStatement без ущерба для производительности?

1 Ответ

2 голосов
/ 14 сентября 2010

Подготовленный оператор просто вставляет введенные вами позиционные значения в повторяющийся оператор, который затем не нужно анализировать каждый раз.Таким образом, ваша вторая форма будет просто требовать N * 3 параметров и не даст вам никакого улучшения скорости подготовленного утверждения.Для повторяющихся утверждений вы хотите использовать addTobatch.По сути, вы готовите оператор (например, «UPDATE ...???», А затем добавляете 3 параметра за раз и выполняете пакет сразу.

Я использовал нечто подобное в качестве утилитычтобы обернуть это беспорядок. Так что вы просто сделаете что-то вроде

  SQLBatchHandler h = new SQLBatchHandler(conn, "UPDATE ... WHERE ? ? ? ... ");
  h.addToBatch(x, y,z);
  h.addToBatch(x2,y2,z2);
  ...
  h.flush();



public class SQLBatchHandler {
    public static int           MAX_BATCH_SIZE  = 500;
    public String           query;
    private Connection      conn;
    private PreparedStatement   ps;
    private int             batch_ct;

    public SQLBatchHandler(Connection c, String query) throws SQLException
        {
        conn = c;
        this.query = query;
        ps = conn.prepareStatement(query);
    }

    /**
     * add this row to the batch and handle the commit if the batch size
     * exceeds {@link #MAX_BATCH_SIZE}
     * 
     * @param values row values
     * @throws SQLException
     */
    public void addToBatch(Object ... values) throws SQLException
    {
        int i = 0;
        for (Object value: values)
        {
            ps.setObject((++i), value);
        }
        add();
    }

    private void add() throws SQLException
    {
        ps.addBatch();
        if ((++batch_ct) > MAX_BATCH_SIZE)
        {
            ps.executeBatch();
            batch_ct = 0;
        }
    }

    /**
     * Commit any remaining objects and close.
     * 
     * @throws SQLException On statement close error.
     */
    public void flush() throws SQLException
    {
        if (batch_ct == 0) { return; }
        try
        {
            ps.executeBatch();
        }
        catch (SQLException e)
        {
            throw e;
        }
        finally
        {
            if (ps != null)
            {
                ps.close();
            }
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...