如何优化查询记录数的SQL操作?

03-04-17 anonymous
我有一个函数用于取给定表名的表记录数,如下:

    /**
     * 取给定表的记录数。
     *
     * @param tableName 表名
     * @return 该表中的记录总数
     */
    public static int getRecoundCount(final String tableName){
        //空值捕获
        if(StringUtil.isNullorBlank(tableName))return 0;
        //记录数
        int count = 0;
        DBOperator dbo = null;
        try{
            dbo =  new DBOperator();
            //TODO: preparestatement...... 优化!!!!!!!!!
            final String sql = "SELECT COUNT(*) FROM " + tableName;
            dbo.setPrepareStatement(sql);
            //dbo.setString(1,tableName);
            final ResultSet rs = dbo.executeQuery();
            //rs.last();
            //count = rs.getRow();
            //取记录数
            if(rs.next()){
                count = rs.getInt(1);
            }
            rs.close();
        }catch(Exception ex){
            ex.printStackTrace();
            log.error(ex.getMessage());
        }finally{
            dbo.close();
            dbo = null;
        }
        return count;
    }//end getRecordCount()

但我测试的数据显示该方法效率很低,目前数据库数据很少,平均在850ms左右,数据库是MYSQL的,好像用count(*)效率不高,但我试过取ID值,然后rs.last();rs.getRow()等,但效率相差无几,而且因为是通用函数,故不可能指定ID名(数据库中主键名都不相同的)

所以想问问高手有什么可以优化的或其他更号效率的方法?

谢谢先:)

另:我本来用preparestatement,但在:

SELECT COUNT(*) FROM (?)时出问题,无法set进这个表名,说sql语法错:(不知道怎么回事:(

Jevang
2003-04-18 00:35
I don't know there is a better way than get count(*) in general.

Maybe you should look at how to cluster the table for better performance, but it varies on database, for mysql, I don't know the option.

I have use getCount(*) in mysql on a table with over 300,000 records, most of time it returns within a couple of seconds. that table reside on INNODB, if you using ISAM, it should even faster, as base on mysql doc, when count(*) with where, it use MyISAM table instead of full table scan.

You can do prepared statement that way, only the param for where can be bind, plus I don't think you have any gain here as with where clause or join, execution plan is very easy to prepared.

wys1978
2003-04-18 09:00
你的这个操作要做到数据库无关性吗?

如果只限制于mysql的话, 你可以用execute

SHOW TABLE STATUS

得到的ResultSet里面的name和rows就是你要的.

如果是要求数据库无关性的话, 可能有2点会对性能有帮助:

1. 先使用ResultSet.last(), 然后用ResultSet.getRow()得到总数, 不同的jdbc driver实现上述的方法不一样, 性能会有很大的差别.

2. 建立statment的时候加上

ResultSet.TYPE_SCROLL_INSENSITIVE

ResultSet.CONCUR_READ_ONLY等优化常数

只读的ResultSet的性能会比其他要好很多.

wys1978
2003-04-18 09:02
又想到一点:

你可以使用table的meta data得到它的primarykey field的名字, 然后建立一个table name和pk field name的mapping cache, 这样就可以不用count(*)了.

anonymous
2003-04-18 13:26
thanks

确实想做到数据库无关,因为有几个功能恨常用,所以想提出来,现在放在一个Sequence类里,比如nextID(final String tableName);getMaxID(final String tableName);getRecordCount(final String tableName)什么的,都使用标准的SQL来做,不过这样放弃了很多数据库的特性,考虑用抽象类,然后具体实现由子类来做,这样就可以使用不同数据库的特性了,而且扩展也容易,构思中,高手给点意见:)谢谢先:)

猜你喜欢
3Go 1 2 3 下一页