Abstract

Updated July 2024

Thanks to Andreas Ledger, RFE INFX-I-368 has been delivered, and this feature is now available in all IDS Editions from version 14.10.FC11 onwards.

Updated February 2026

The procedure provided to generate implementation SQL now fully handles foreign key constraints and has new parameters.


Best practice has always been not to create indexes on highly duplicate data. Scanning the entire table for a common value may be quicker, and updating an index can be very costly when many pointers to rows with the same value are spread over several pages. A work-around when an index is essential in this scenario is to extend the index with a more selective column, but this obviously makes it bigger.

For the first time, a far better solution was provided in IDS 14.10.FC2, known as Partial Indexes (click for the relevant page in the IBM Knowledge Center).

In this article, we will demonstrate how to identify where such indexes might be appropriate, how to create them, and how much smaller they can potentially be.

Content

A classic example is the index on the “status” column of the Sage Line 500 “opheadm” table which contains sales orders. 99% of rows will typically have the value “8” for “Invoiced” in the status column: if we wanted to retrieve all those rows, the query optimizer will probably find it quicker to scan the whole table without using any index. However, most of the time, we are looking for rows with one of the other values, for which we do need an index. The following simulates the scenario (the real table obviously has many more columns):

Copy to Clipboard

That returns:

statusnumber
11000
21000
31000
41000
51000
61000
71000
8993000

The standard index has 2783 used pages, 2766 leaves, and 3 levels.

SQL to replace this with a partial index excluding invoiced rows is:

Copy to Clipboard

  • Stating the dbspace name before “INDEX OFF” is recommended as it’s necessary for mixed page sizes: see Caveats.
  • Partition names can be whatever you like instead of “part_0” and “part_1” within the normal Informix object name rules.

The new index has 24 used pages, 22 leaves, and 2 levels.

The following function helps you identify indexes that could be candidates, and generates SQL to replace them with partial indexes:

Copy to Clipboard

It checks all duplicate indexes on single columns in a specified database to see if there are values accounting for more than a given percentage of rows in the table. For example, create and populate the example table as described in the IBM Knowledge Center Partial Indexes page, but with this index:

Copy to Clipboard

Then run the new function:

Copy to Clipboard

SQL generated:

Copy to Clipboard

The number of leaves, levels and rows is shown so that you can decide which indexes are big enough to matter, plus the largest percentage of rows with a column value to be excluded from the index

Run on the standard demo database:

Copy to Clipboard

SQL generated:

Copy to Clipboard

Additional statements are required for indexes supporting foreign keys. The constraint must be dropped first, without which we cannot rebuild the index. There are two scenarios regarding whether we also need to drop the index explicitly:

  1. If the index was previously created automatically by an ADD CONSTRAINT statement, it is hidden and has a name beginning with a space followed by the table ID and a sequential number. It will be dropped with the constraint. In order to recreate it separately before the constraint is added back, it must have a valid name that does not begin with a space, so the procedure replaces the leading space with “ix_”.
  2. If the index was previously created explicitly before an ADD CONSTRAINT statement, it must be dropped explicitly after the constraint.

The procedure handles all of that. You will also find that the generated SQL always begins with:

Copy to Clipboard

That makes it way quicker to recreate constraints, as it doesn’t then pointlessly recheck column values in the referenced table: they must have been there just before when the constraint already existed.

The full set of parameters are:

  1. Database if different to where the function is defined
  2. Percentage of rows for a column value to be a candidate (default 50%)
  3. Minimum number of rows for the table to be included (default 1000)
  4. Skip indexes supporting foreign key constraints (default off)

You may want to experiment with different thresholds in 2 and 3. We recommend using the defaults as a  starting point, but you can change those in the code as is suitable for your system:

  • 50% means you will only ever have one column value listed, which keeps it simple, and is a good compromise between saving space but still indexing values that might have a purpose.
  • Less than 1000 rows is the normal definition of a “small table” for Automated Update Statistics and the Query Optimizer. The index will quite likely not be used and its size will be trivial, so we might as well exclude it from the generated SQL to keep it shorter.

Caveats

Tables comprised of multiple fragments (partitions) is part of the parallelisation features normally reserved for Enterprise Edition. Partial indexes have been implemented using the same FRAGMENT BY EXPRESSION (or PARTITION) syntax, and this was rejected on lower editions (except Developer) with error 26453 “Fragmentation is not supported in this edition of IDS” prior to 14.10.FC11.

This article was updated in August 2020 with new information from Roland Wintgen who opened a case with IBM. A problem occurs if the database or table is in a dbspace with a non-default page size. For example, in an instance with 2KB pages by default, if you create a 4KB page dbspace “data4kb” then a new database in it, the following simpler form of SQL for one of our examples produces an error:

Copy to Clipboard

You have to declare a dbspace name for both fragments in this situation. Perhaps it otherwise defaults to the root dbspace, causing the error. However, it still fails:

Copy to Clipboard

The solution is also to name the fragments (aka. partitions):

Copy to Clipboard

The stored procedure and examples in this article were amended accordingly. If accepted as a bug by IBM, we will provide further updates here with the defect number and IDS version containing the fix when either are known. Meanwhile, the above is a full work-around.

Conclusion

If Informix 14.10 Partial Indexes are available in your version and edition, they may save you considerable disk space and make reads, inserts and deletes lighter.

Disclaimer

Suggestions above are provided “as is” without warranty of any kind, either express or implied, including without limitation any implied warranties of condition, uninterrupted use, merchantability, fitness for a particular purpose, or non-infringement.

Contact us

If you have any questions regarding Informix 14.10 Partial Indexes or would like to find out more, simply contact us.

Author