SELECT COUNT(*) FROM mytable is a very quick operation on IBM i. I've got a table with almost 17 million rows and the above comes back instantly. And I have one of the smaller and older boxes available.
It's only when you add the WHERE clause that things may slow down. As with any other operation on any DB, indexes play an important role. Actually, the IBM i has an advantage over most (every?) other DB's out there when it comes to counting rows. IBM i supports the standard bitmapped index like any other DB; but it also supports another index type called encoded vector index (EVI). I won't go into all the details, but for the purposes of counting rows and EVI index is quite useful as the row count for each key is part of the index itself. As you can imagine, this makes counting rows with a matching key pretty much instant.
Going back to your code
[IBM][iSeries Access ODBC Driver][DB2 UDB]SQL0204 - PARTITIONS in SYS type *FILE not found.
The error is pretty clear. There's no SYS.PARTITIONS table in IBM i. SYS.PARTITIONS is not an ANSI/ISO standard catalog nor a JDBC/ODBC standard one; it's MS SQL Server specific.
Available DB2 for IBM i catalog views for the latest release (7.2) are shown here:
http://www-01.ibm.com/support/knowledgecenter/ssw_ibm_i_72/db2/rbafzcatalog.htm
For v5r4 (5.4), look here:
http://www-01.ibm.com/support/knowledgecenter/ssw_i5_54/db2/rbafzmstcatalog.htm
It appears that SYSPARTITIONSTAT in QSYS2 is the closest IBM i has to MS SQL's SYS.PARTITIONS. However, there's no OBJECT_ID or INDEX_ID column.
If all you're after is a row count, I'd simply use...
SELECT COUNT(*)
FROM MYLIB.MYTABLE
As it should return pretty much instantly. You'll have some overhead by going through the linked server. To see how much, use either an IBM tool such as the (green screen) STRSQL or (Java) iNav's Run SQL Scripts to run the query directly. SQuirreL could be used also.
If you really want to query the meta data, then:
SELECT NUMBER_ROWS
FROM QSYS2.SYSPARTITIONSTAT
WHERE TABLE_NAME = 'MYTABLE'
AND TABLE_SCHEMA = 'MYLIB'
*Note there's also a SYSTEM_TABLE_NAME and SYSTEM_TABLE_SCHEMA column containing the 10 charactor system table & schema name.
But I'd be surprised if it performed any faster. On my system, over that 17M row table, SELECT COUNT(*) took 39ms and querying SYSPARTITIONSTAT took 135ms.
Looking at your added COUNT(*) code...
The LIKE ''%Peter%'' is going to hurt performance as an index lookup can't be used. At best, you're looking at a full index scan. Make sure you have an index the system can use. I would try 3 separate scenarios and see which index the system uses. (Use the Run & Explain in iSeries Navigator's Run SQL Scripts)
- separate (bitmapped) index over each column
- separate EVI index over each column
- 1 combined (First middle last) (bitmapped) index over all three columns
Also have you tried the format
WHERE P.FirstName like ''%Peter%''
OR P.MiddleName like ''%Peter%''
OR P.LastName like ''%Peter%''
That should allow the DB to search less work especially if most the matches come from P.FirstName, plus it doesn't have to use any temporary storage to concatenate the data. Note: I also got rid of the TRIM() it's not needed in either case. I suspect it's costing you some. It's possible it helps, but in that case TRIMR() would be better. The best solution would be to have variable length columns in the first place.
It's possible that your original format (with or without the TRIM() might be more conducive to the third index option above (1 combined index). Whereas the other two index options would be more conducive to the first two options.
Create all 7 indexes mentioned above then try the various scenarios using Run & Explain to see what's happening which each one.
In between tries,
- disconnect and reconnect from the system
- use the SETOBJACC OBJ(PERSON) OBJTYPE(*FILE) POOL(*PURGE)
That should keep caching to a minimum and the comparisons equal.
COUNT()and even though the time differences are not that significant the one where I look for matches in the name (like in the example) is the slowest one. But I also use columns fromINFin the where clause and I need to count the result in that case also. So the full query needs this join no matter that in this example I use column from the first table.