JDBC SELECT очень медленный по сравнению с менеджером БД Firefox - PullRequest
4 голосов
/ 02 апреля 2012

Решено , конечно после публикации здесь меня поразило ... Теперь используются разные драйверы из http://www.xerial.org/trac/Xerial/wiki/SQLiteJDBC#Download, которые не нуждаются в расширенной настройке.

Оригинальный вопрос ниже перерыва.


Я дурачусь с базой данных SQLite, содержащей данные OpenStreetMap, и у меня возникли некоторые проблемы с JDBC.

Запрос ниже - это тот, который я хотел бы использовать, чтобы быстро найти местоположение, близкое к местоположению моего пользователя (числа взяты из моих тестовых данных и добавлены кодом java).

SELECT roads.nodeID, lat, lon 
FROM roads 
INNER JOIN nodes 
ON roads.nodeID=nodes.nodeID 
ORDER BY (ABS(lat - (12.598418)) + ABS(lon - (-70.043514))) ASC 
LIMIT 1

'дороги' и 'узлы' содержат приблизительно 130 000 строк.

Этот конкретный запрос - один из самых интенсивных, он используется только дважды, так что он будет в порядке для моих нужд. При использовании Firefox SQLite он выполняется примерно за 281 мс, но в Java с использованием sqlitejdbc-v056 это занимает от 12 до 14 секунд (при полной загрузке процессора).

Есть какие-нибудь подсказки, как это исправить?

public Node getNodeClosestToLocation(Location loc){
        try {
            Class.forName("org.sqlite.JDBC");
            Statement stat = conn.createStatement();
            String q = "SELECT roads.nodeID, lat, lon "+
            "FROM roads "+
            "INNER JOIN nodes "+
            "ON roads.nodeID=nodes.nodeID "+
            "ORDER BY (ABS(lat - ("+loc.getLat()+")) +
            ABS(lon - ("+loc.getLon()+"))) ASC "+
            "LIMIT 1";
            long start = System.currentTimeMillis();
            System.out.println(q);

            rs = stat.executeQuery(q);
            if(rs.next()) {
                System.out.println("Done. " + (System.currentTimeMillis() - start));

                return new Node(rs.getInt("nodeID"), rs.getFloat("lat"), rs.getFloat("lon"));
            }   

        }
        catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }

Ответы [ 2 ]

1 голос
/ 05 июня 2012

Когда дело доходит до выбора запросов операторов в JDBC, они могут быть очень болезненно медленными, если они не используются правильно. Несколько баллов:

  1. Убедитесь, что вы указали правильные столбцы в вашей таблице. Простая строка, такая как:

Statement stat = connection.createStatement();<br> stat.executeUpdate("create index {index_name} on orders({column_name});");<br> stat.close();

Создание индекса: http://www.w3schools.com/sql/sql_create_index.asp

  1. Вставка занимает больше времени с индексами, поскольку каждый предыдущий индекс должен обновляться по мере добавления новых записей. Создание индекса лучше всего делать после того, как все операторы вставки были выполнены (лучшая производительность). Индексированные столбцы оказывают значительное влияние на производительность вставки, но имеют значительно более высокую производительность выделения.

  2. Изменение драйвера JDBC может немного помочь, но в целом не должно быть основной проблемой. Также убедитесь, что вы работаете в основном режиме. Режим Pure-Java значительно медленнее, по крайней мере из того, что я заметил. Следующий фрагмент кода скажет вам, в каком режиме вы работаете, при условии, что вы используете SQLite JDBC.

System.out.println(String.format("%s mode", SQLiteJDBCLoader.isNativeMode() ? "native" : "pure-java"));

У меня возникла та же проблема с медленным выбором в базе данных с более чем 500K записями. Время выполнения моего приложения было бы 9,9 дней, если бы я не проиндексировал. Теперь это невероятно быстро 2 минуты, чтобы сделать то же самое. SQLite очень быстр, когда используется правильный и оптимизированный sql.

0 голосов
/ 27 мая 2012

Использование PreparedStatement может дать вам немного лучшую производительность, но ничто из величины, описанной здесь.

Возможно, Firefox SQLite использует некоторые подсказки. Вы можете попытаться получить план выполнения, чтобы увидеть, где запрос выполняет тяжелую работу, и при необходимости создать некоторый индекс.

Вы пытались зарегистрировать любую информацию о времени, чтобы убедиться, что она не получает дорогостоящее соединение?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...