milesibastos / jTDS

jTDS JDBC Driver
http://jtds.sourceforge.net/
GNU Lesser General Public License v2.1
81 stars 46 forks source link

When there are many columns in the database table, the cpu is 100% #17

Open g-senlin opened 3 years ago

g-senlin commented 3 years ago

There are many columns in the database table and SQL queries all fields, the cpu is 100% , because the initialization strategy of JtdsResultSet#columnMap is wrong.

Please see the code below

https://github.com/milesibastos/jTDS/blob/master/src/main/net/sourceforge/jtds/jdbc/JtdsResultSet.java

code issues

public int findColumn(String columnName) throws SQLException {
        checkOpen();

        if (columnMap == null) {
            columnMap = new HashMap(columnCount);
        } else {
            Object pos = columnMap.get(columnName);//  columnMap cache won't hit
            if (pos != null) {
                return ((Integer) pos).intValue();
            }
        }

        // Rather than use toUpperCase()/toLowerCase(), which are costly,
        // just do a sequential search. It's actually faster in most cases.
        for (int i = 0; i < columnCount; i++) {
            if (columns[i].name.equalsIgnoreCase(columnName)) {
                columnMap.put(columnName, new Integer(i + 1)); // initialization strategy of columnMap is wrong

                return i + 1;
            }
        }

        throw new SQLException(Messages.get("error.resultset.colname", columnName), "07009");
    }

Modified code

I use sybase database, the query columns of sql are all uppercase, if you want to be ignore case , you need to modify it

    public int findColumn(String columnName) throws SQLException {
        checkOpen();

        if (columnMap == null) {
//           init cache 
            columnMap = new HashMap(columnCount);
            for (int i = 0; i < columnCount; i++) {
                columnMap.put(columns[i].name, new Integer(i + 1));
            }
        }

        Object pos = columnMap.get(columnName);
        if (pos != null) {
            return ((Integer) pos).intValue();
        }

        // Rather than use toUpperCase()/toLowerCase(), which are costly,
        // just do a sequential search. It's actually faster in most cases.
        for (int i = 0; i < columnCount; i++) {
            if (columns[i].name.equalsIgnoreCase(columnName)) {
                columnMap.put(columnName, new Integer(i + 1));

                return i + 1;
            }
        }

        throw new SQLException(Messages.get("error.resultset.colname", columnName), "07009");
    }