| /* |
| * Derby - Class org.apache.derbyTesting.perf.basic.jdbc.IndexScanTest |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, |
| * either express or implied. See the License for the specific |
| * language governing permissions and limitations under the License. |
| */ |
| |
| package org.apache.derbyTesting.perf.basic.jdbc; |
| |
| import java.sql.PreparedStatement; |
| import java.sql.ResultSet; |
| import java.sql.SQLException; |
| import java.sql.Statement; |
| import java.util.Random; |
| import junit.framework.Test; |
| import org.apache.derbyTesting.junit.BaseTestSuite; |
| import org.apache.derbyTesting.junit.CleanDatabaseTestSetup; |
| import org.apache.derbyTesting.junit.JDBCPerfTestCase; |
| |
| /** |
| * Test the performance of different kinds of index scans. This test was |
| * written in order to test the performance impact of the changes made in |
| * DERBY-2991. |
| */ |
| public class IndexScanTest extends JDBCPerfTestCase { |
| |
| /** The prepared statement for the SQL expression that we want to test. */ |
| private PreparedStatement preparedStmt; |
| |
| /** |
| * Create an instance of the test. |
| * @param name the name of the method to call in the test |
| * @param iterations the number of iteration in each test run |
| * @param repeats the number of times each test run is repeated |
| */ |
| private IndexScanTest(String name, int iterations, int repeats) { |
| super(name, iterations, repeats); |
| } |
| |
| /** |
| * Get the prepared statement that we use in the test. If this is the |
| * first time the method is called on this object, prepare the statement |
| * and then return it. |
| * @param sql the SQL text to prepare if the statement isn't already |
| * compiled |
| * @return the prepared statement to use in this test |
| */ |
| private PreparedStatement getOrPrepareStatement(String sql) |
| throws SQLException { |
| if (preparedStmt == null) { |
| preparedStmt = prepareStatement(sql); |
| } |
| return preparedStmt; |
| } |
| |
| /** |
| * Do the necessary clean-up after running the test. |
| */ |
| protected void tearDown() throws Exception { |
| super.tearDown(); |
| // Null out the statement to allow it to be gc'ed. It will be closed |
| // automatically by the framework. |
| preparedStmt = null; |
| } |
| |
| /** |
| * Create a test suite with all the test cases in this class. |
| * @return a test suite |
| */ |
| public static Test suite() { |
| BaseTestSuite suite = new BaseTestSuite("IndexScanTest"); |
| suite.addTest(new IndexScanTest("varchar10", 5000, 4)); |
| suite.addTest(new IndexScanTest("varchar100", 5000, 4)); |
| suite.addTest(new IndexScanTest("varchar1000", 5000, 4)); |
| suite.addTest(new IndexScanTest("varcharAll", 5000, 4)); |
| suite.addTest(new IndexScanTest("decimal1column", 5000, 4)); |
| suite.addTest(new IndexScanTest("decimal10columns", 5000, 4)); |
| |
| return new CleanDatabaseTestSetup(suite) { |
| protected void decorateSQL(Statement s) throws SQLException { |
| // Create a table with some character data and decimal data |
| // that we can use in our tests. |
| s.execute("CREATE TABLE T (VC10 VARCHAR(10), " + |
| "VC100 VARCHAR(100), " + |
| "VC1000 VARCHAR(1000), " + |
| "DEC1 DECIMAL(10,10), " + |
| "DEC2 DECIMAL(10,10), " + |
| "DEC3 DECIMAL(10,10), " + |
| "DEC4 DECIMAL(10,10), " + |
| "DEC5 DECIMAL(10,10), " + |
| "DEC6 DECIMAL(10,10), " + |
| "DEC7 DECIMAL(10,10), " + |
| "DEC8 DECIMAL(10,10), " + |
| "DEC9 DECIMAL(10,10), " + |
| "DEC10 DECIMAL(10,10))"); |
| |
| // Fill the table with 1000 rows containing random data. |
| PreparedStatement ps = s.getConnection().prepareStatement( |
| "INSERT INTO T(VC10,VC100,VC1000,DEC1,DEC2,DEC3," + |
| "DEC4,DEC5,DEC6,DEC7,DEC8,DEC9,DEC10) VALUES (?,?,?," + |
| "RANDOM(),RANDOM(),RANDOM(),RANDOM(),RANDOM()," + |
| "RANDOM(),RANDOM(),RANDOM(),RANDOM(),RANDOM())"); |
| char[] chars = new char[1000]; |
| Random r = new Random(); |
| for (int i = 0; i < 1000; i++) { |
| fillWithRandomChars(r, chars); |
| ps.setString(1, new String(chars, 0, 10)); |
| ps.setString(2, new String(chars, 0, 100)); |
| ps.setString(3, new String(chars, 0, 1000)); |
| ps.executeUpdate(); |
| } |
| ps.close(); |
| |
| // Create various indexes on the table. |
| s.execute("CREATE INDEX T_VC10 ON T(VC10)"); |
| s.execute("CREATE INDEX T_VC100 ON T(VC100)"); |
| s.execute("CREATE INDEX T_VC1000 ON T(VC1000)"); |
| s.execute("CREATE INDEX T_VC_ALL ON T(VC10,VC100,VC1000)"); |
| s.execute("CREATE INDEX T_DEC1 ON T(DEC1)"); |
| s.execute("CREATE INDEX T_DEC_ALL ON T(DEC1,DEC2,DEC3,DEC4," + |
| "DEC5,DEC6,DEC7,DEC8,DEC9,DEC10)"); |
| } |
| }; |
| } |
| |
| /** |
| * Fill a {@code char} array with random characters. |
| * @param r a random number generator |
| * @param chars the array to fill |
| */ |
| private static void fillWithRandomChars(Random r, char[] chars) { |
| String alphabet = |
| "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; |
| for (int i = 0; i < chars.length; i++) { |
| chars[i] = alphabet.charAt(r.nextInt(alphabet.length())); |
| } |
| } |
| |
| /** |
| * Test the performance of an index scan on a VARCHAR(10) column. |
| */ |
| public void varchar10() throws SQLException { |
| PreparedStatement ps = getOrPrepareStatement( |
| "SELECT VC10 FROM T --DERBY-PROPERTIES index=T_VC10"); |
| ResultSet rs = ps.executeQuery(); |
| while (rs.next()) { |
| assertNotNull(rs.getString(1)); |
| } |
| rs.close(); |
| } |
| |
| /** |
| * Test the performance of an index scan on a VARCHAR(100) column. |
| */ |
| public void varchar100() throws SQLException { |
| PreparedStatement ps = getOrPrepareStatement( |
| "SELECT VC100 FROM T --DERBY-PROPERTIES index=T_VC100"); |
| ResultSet rs = ps.executeQuery(); |
| while (rs.next()) { |
| assertNotNull(rs.getString(1)); |
| } |
| rs.close(); |
| } |
| |
| /** |
| * Test the performance of an index scan on a VARCHAR(1000) column. |
| */ |
| public void varchar1000() throws SQLException { |
| PreparedStatement ps = getOrPrepareStatement( |
| "SELECT VC1000 FROM T --DERBY-PROPERTIES index=T_VC1000"); |
| ResultSet rs = ps.executeQuery(); |
| while (rs.next()) { |
| assertNotNull(rs.getString(1)); |
| } |
| rs.close(); |
| } |
| |
| /** |
| * Test the performance of an index scan with a compound index on |
| * columns with type VARCHAR(10), VARCHAR(100) and VARCHAR(1000). |
| */ |
| public void varcharAll() throws SQLException { |
| PreparedStatement ps = getOrPrepareStatement( |
| "SELECT VC10,VC100,VC1000 FROM T --DERBY-PROPERTIES index=T_VC_ALL"); |
| ResultSet rs = ps.executeQuery(); |
| while (rs.next()) { |
| for (int col = 1; col <= 3; col++) { |
| assertNotNull(rs.getString(col)); |
| } |
| } |
| rs.close(); |
| } |
| |
| /** |
| * Test the performance of an index scan on a DECIMAL(10,10) column. |
| */ |
| public void decimal1column() throws SQLException { |
| PreparedStatement ps = getOrPrepareStatement( |
| "SELECT DEC1 FROM T --DERBY-PROPERTIES index=T_DEC1"); |
| ResultSet rs = ps.executeQuery(); |
| while (rs.next()) { |
| assertNotNull(rs.getBigDecimal(1)); |
| } |
| rs.close(); |
| } |
| |
| /** |
| * Test the performance of an index scan on a compound index on ten |
| * DECIMAL(10,10) columns. |
| */ |
| public void decimal10columns() throws SQLException { |
| PreparedStatement ps = getOrPrepareStatement( |
| "SELECT DEC1,DEC2,DEC3,DEC4,DEC5,DEC6,DEC7,DEC8,DEC9,DEC10 " + |
| "FROM T --DERBY-PROPERTIES index=T_DEC_ALL"); |
| ResultSet rs = ps.executeQuery(); |
| while (rs.next()) { |
| for (int col = 1; col <= 10; col++) { |
| assertNotNull(rs.getBigDecimal(col)); |
| } |
| } |
| rs.close(); |
| } |
| } |