1

入力として座標を指定すると、特定の半径からプロバイダーを返す Java EE でロケーションベースのアプリケーションを構築しようとしています。JPAを使用しているため、Sin、 Cosなどの関数をサポートしていないため、名前付きクエリでデータベースをクエリする解決策を見つけることができませんでした。代わりにクエリを実行します。クエリはデータベース (Postgres) では高速 (33 ミリ秒) に実行されますが、アプリケーションから実行すると非常に遅くなります (> 800 ミリ秒)。

アプリケーション側から高速化する方法はありますか、それともデータベースでストアド プロシージャのようなものを使用する必要がありますか。

私の方法は次のようになります。

@SuppressWarnings("unchecked")
public List<Company> findCompaniesByProximity(Coordinate coordinate, int distance) {
    double latitude = coordinate.getLatitude();
    double longitude = coordinate.getLongitude();
    String sql = "SELECT * FROM ("
            + "SELECT *, c.distance_unit * DEGREES(ACOS(COS(RADIANS(c.lat)) * COS(RADIANS(companies.latitude)) * "
            + "COS(RADIANS(c.lng) - RADIANS(companies.longitude)) + SIN(RADIANS(c.lat)) * SIN(RADIANS(companies.latitude)))"
            + ") AS distance "
            + "FROM Companies "
            + "JOIN (SELECT  ?1 AS lat, ?2 AS lng, ?3 AS search_radius, 111.045 AS distance_unit) "
            + "AS c ON 1=1 "
            + "WHERE companies.latitude "
            + "BETWEEN c.lat  - (c.search_radius / c.distance_unit) "
            + "AND c.lat  + (c.search_radius / c.distance_unit) "
            + "AND companies.longitude "
            + "BETWEEN c.lng - (c.search_radius / (c.distance_unit * COS(RADIANS(c.lat)))) "
            + "AND c.lng + (c.search_radius / (c.distance_unit * COS(RADIANS(c.lat))))"
            + ") AS proximity "
            + "WHERE distance <= search_radius "
            + "ORDER BY distance "
            + "LIMIT 25";
    List<Company> companies = null;
    try {
        Query query = em.createNativeQuery(sql, Company.class);
        query.setParameter(1, latitude);
        query.setParameter(2, longitude);
        query.setParameter(3, distance / 1000.0);
        companies = (List<Company>) query.getResultList();
    } catch (IllegalArgumentException e) {
        System.err.println("Argument is invalid " + e);
    } catch (PersistenceException e) {
        System.err.println("PersistenceException: " + e.getMessage());
    }
    return companies;
}

メソッドはシングルトン EJB から呼び出され、Payara サーバーと Postgres および EclipseLink を使用しています。すべてがローカルで呼び出されるため、データベースへの接続がはるかに高速になると思いました。私はpostgresのearthdistance拡張機能も試しましたが、さらに遅くなりました(> 1800ミリ秒)。私はプログラミング、特にJava EEにまったく慣れていないので、途中で何か間違ったことをしたかもしれません:)よろしくお願いします。

4

0 に答える 0