0

我的数据库表(geo ip 查找)有 7 列,其中 2 列构成 <composite-id>。现在,当我使用前 2 个列查找值时,我需要12-14 秒才能获取记录..

我的 DAO 代码如下所示:

String queryString = "from Igeo igeo where igeo.ip_from <= " + ip
            + "and igeo.ip_to >= " + ip;

    Query q = session.createQuery(queryString);
    List<Igeo> igeoList = q.list();

    if(igeoList.size() > 0){
        Igeo igeo = igeoList.get(0);

        ISP = igeo.getIsp();
        ...
        ...         
    }

*Igeo = java 代表表中的类

**当 ip 位于复合 ID 列的值之间时获取记录,例如。

ip_from = 1 ; ip_to = 3 ; ip = 2;

所以上面的行将被返回

该表仅用于读取记录,请给我一个比上面更有效的查询字符串

4

2 回答 2

4

首先删除休眠并在查询浏览器中运行您的查询,看看需要多长时间才能返回。如果花费相同的时间,则不是休眠。这是数据库的性能。确保将索引添加到两列 ip_from 和 ip_to。您还可以对查询执行查询计划,以查看数据库在后台运行的内容并尝试优化查询计划。

我建议不要像你一样在查询中使用连接。这会产生一个安全漏洞,允许来自外部各方的潜在 SQL 注入。最好使用以下内容:

Query q = session.createQuery("from Igeo igeo where igeo.from_ip >= ? and igeo.to_ip <= ?");
q.setString( 0, ip );
q.setString( 1, ip );

您还可以使用命名参数,这可能会缩短一点。

于 2012-07-24T14:47:09.293 回答
0

如果表 IGeo 不包含 ip_from 和 ip_to 的重叠范围,您可以试试这个

    String queryString = "FROM Igeo igeo"
        +  " WHERE igeo.ip_to >= " + ip
        +  " ORDER BY igeo.ip_to";

然后检查列表中的第一项(查看 ip_from <= ip)。

即使该表可能包含 ip_from、ip_to 的重叠范围,我敢打赌上述 HQL 会运行得更快。

<除了>你真的不应该将像“ip”这样的原始字符串连接到 HQL 或 SQL 中。它会导致 SQL 注入攻击漏洞。使用查询参数代替</Aside>

此外,验证您的数据库在对应于 Igeo.ip_to 的列上有一个索引。

根据您的描述,我觉得数据库的主键是 Igeo.ip_from + IGeo.ip_to。如果 ip_from 和 ip_to 的值不重叠,那似乎没有被规范化。您应该只需要一列作为主键。如果您选择将两列都用作主键,则上述查询将受益于添加单个索引。

如果您添加一个包含表中所有列的索引(从 ip_to 和 ip_from 开始),某些数据库的性能会更好。(这使数据库能够通过仅访问索引来满足查询)。不确定 MySQL 是否可以优化到这种程度,但我知道 DB2 和 Oracle 会提供这一点。

于 2012-07-24T14:57:40.333 回答