Sunday, November 2, 2025

Optimizing Composite Indexes in Oracle

Optimizing Composite Indexes in Oracle: Balancing Selectivity and Index Skip Scan


How to Decide the Leading Column Order in Oracle Composite Indexes? (Using Index Skip Scan Effectively)

As a Developer or Application DBA you may have challenges to setting fist column in composite indexes as a Leading Column based on many SQL statements in your environment, in this topic I demonstrate all aspects of these situations and finally present a formula to handling these type of concerns.

In the previous post, I have a comparison between Oracle and PostgreSQL in Skip Scan concept, it it better to fist visit mentioned post to get a deeply detailed guide.

https://lnkd.in/dP6f3hU2

๐Ÿ”น 1. General rule: leading column should be highly selective

In most cases, Oracle recommends that the most selective column should come first in a composite index.

Reason:
• The optimizer can use the index efficiently when filtering by the first column.
• The fewer rows per key value, the faster it can find matching entries.

Example:

CREATE INDEX idx_t_color_machine ON t (machine_id, color);

If machine_id has many distinct values (high selectivity), this is good when most queries filter on machine_id first.

๐Ÿ”น 2. Problem: what if your queries filter by different combinations?
Let’s say you have queries like:

SELECT * FROM t WHERE color = 'BLUE';
SELECT * FROM t WHERE color = 'RED' AND machine_id = 123;
SELECT * FROM t WHERE machine_id = 123;

Now you have a dilemma:
• If you make (color, machine_id) → good for the first two, bad for the third.
• If you make (machine_id, color) → good for the last two, bad for the first.

So what’s best?

๐Ÿ”น 3. Enter: Index Skip Scan

Oracle can skip scan a composite index when the leading column is not specified in the WHERE clause — but only if the leading column has low cardinality (few distinct values).

So if color has few values like 'RED', 'BLUE', 'GREEN', and machine_id is very selective, then:

CREATE INDEX idx_t_color_machine ON t (color, machine_id);

is actually useful for all these:
• WHERE color = 'BLUE' → normal index range scan
• WHERE color = 'RED' AND machine_id = 123 → normal index range scan
• WHERE machine_id = 123 → index skip scan may kick in
Oracle internally scans index partitions per color value and then looks for machine_id=123.
This is efficient only if the number of distinct color values is small.

๐Ÿ”น 4. Summary table

▶️ If most queries filter on one specific column (and it’s highly selective):
→ Put that selective column first in the index.
Reason: Oracle can use it directly for fast lookups.

▶️ If most queries filter on both columns together:
→ Put the most selective column first.
Reason: Classic composite index design — minimizes scanned rows.

▶️ If some queries omit the first column, and that column has low cardinality (few distinct values):
→ Put that low-cardinality column first.
Reason: Enables Index Skip Scan, allowing Oracle to still use the index efficiently even when the first column isn’t in the WHERE clause.

▶️ If some queries omit the first column, and that column has high cardinality (many distinct values):
→ Don’t rely on skip scans — instead, create separate indexes for different query patterns.
Reason: Skip scans become inefficient when the leading column has too many distinct values.

๐Ÿ”น 5. example
Index created on  (color, machine_id)
And queries are:

1. SELECT * FROM table WHERE color = 'blue';
2. SELECT * FROM table WHERE color = 'red' AND machine_id = 123;
3. SELECT * FROM table WHERE machine_id = 123;

If:
• color = low cardinality (say 5–10 colors)
• machine_id = high cardinality (many machines)

Then  (color, machine_id) is actually best:
• #1 and #2 → normal index scan
• #3 → index skip scan (because color has few distinct values)

But if:
• color = high cardinality (hundreds of distinct values)
• machine_id = low cardinality
Then skip scan will be expensive → better to use (machine_id, color) or two separate indexes.

๐ŸŸช Final Recommendation

IF (leading column used in most queries)
    THEN make it leading
ELSE IF (leading column has low cardinality AND others have high)
    THEN put low-cardinality column first (for skip scan)
ELSE
    use separate indexes;

Saturday, November 1, 2025

Database 26ai Installation Guide

 Database 26ai Installation Guide


In this topic, I explain two new and important steps when installing Oracle new versions as 26ai:


Setting Clock Source for VMs on Linux x86-64

Oracle recommends that you set the clock source to tsc for better performance in virtual

environments (VM) on Linux x86-64.


As the root user, check if the tsc clock source is available on your system.

# cat /sys/devices/system/clocksource/clocksource0/available_clocksource

kvm-clock tsc acpi_pm

If the tsc clock source is available, then set tsc as the current clock source.

# echo "tsc">/sys/devices/system/clocksource/clocksource0/

current_clocksource

Verify that the current clock source is set to tsc.

# cat /sys/devices/system/clocksource/clocksource0/current_clocksource

tsc

Using any text editor, append the clocksource directive to the GRUB_CMDLINE_LINUX line in

the /etc/default/grub file to retain this clock source setting even after a reboot.

GRUB_CMDLINE_LINUX="rd.lvm.lv=ol/root rd.lvm.lv=ol/swap rhgb quiet

numa=off transparent_hugepage=never clocksource=tsc"

Run the following command to update GRUB and ensure that these settings are retained

even after a reboot:

# grub2-mkconfig -o /boot/grub2/grub.cfg


Setting Transparent HugePages to madvise

Transparent HugePages memory is enabled by default with Oracle Linux. 


๐Ÿ“•However, for optimal

performance, Oracle recommends that you set Transparent HugePages to madvise on all

Oracle Database servers UEK7 and later kernels and not disable Transparent HugePages as

was recommended in prior releases.๐Ÿ‘ˆ


If you install Oracle Database Preinstallation RPM, then it sets Transparent HugePages to

madvise on all Oracle Database servers UEK7 and later kernels.


To set madvise on Transparent HugePages:


For Oracle Linux and Red Hat Enterprise Linux, add or modify the

transparent_hugepage=madvise parameter in the /etc/default/grub file:

GRUB_TIMEOUT=5

GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)"

GRUB_DEFAULT=saved

GRUB_DISABLE_SUBMENU=true

GRUB_TERMINAL_OUTPUT="console"

GRUB_CMDLINE_LINUX="crashkernel=auto rhgb quiet

transparent_hugepage=madvise"

GRUB_DISABLE_RECOVERY="true"

Note:

The file name may vary depending on your operating system and hardware. For

example, on Oracle Cloud Infrastructure (OCI) the grub.cfg file is located at /boot/efi/EFI/redhat/

Check your operating system documentation for the exact file name.


Run the grub2–mkconfig command to regenerate the grub.cfg file.

On Oracle Linux 8

# grub2-mkconfig -o /boot/grub2/grub.cfg

On Oracle Linux 9

grub2-mkconfig -o /boot/grub2/grub.cfg --update-bls-cmdline

Restart the system to make the changes permanent. If you do not want to restart your

system, then enter the following command:

# echo madvise >

/sys/kernel/mm/transparent_hugepage/enabled

To check if Transparent HugePages is enabled and configured with madvise, run one of

the following commands as the root user:

Oracle Linux kernels:

# cat /sys/kernel/mm/transparent_hugepage/enabled

Red Hat Enterprise Linux kernels:

# cat /sys/kernel/mm/redhat_transparent_hugepage/enabled

The following is a sample output that shows Transparent HugePages is being used and set

to madvise.

always [madvise] never


What is THP:

Transparent HugePages (THP) is a Linux kernel feature that automates the use of large memory pages (typically 2MB instead of the standard 4KB) to improve memory management efficiency and application performance. Here’s a breakdown of what it is and why Oracle 26ai recommends setting it to `madvise`:


What Are Transparent HugePages?

Purpose: THP reduces overhead in memory management by using larger memory pages, which means fewer pages to track and manage.

Benefit: This can lead to better performance for applications with large memory footprints, like Oracle databases.

Modes:• `always`: Kernel tries to use hugepages for all memory allocations.

• `madvise`: Kernel uses hugepages only when applications explicitly request them via the `madvise()` system call.

• `never`: THP is disabled entirely.


Why Oracle 26ai Recommends `madvise` on UEK7+

Oracle previously advised disabling THP due to performance unpredictability and latency spikes. However, with improvements in UEK7 (Unbreakable Enterprise Kernel version 7) and later:


Improved THP behavior: Kernel enhancements have made THP more stable and predictable.


Selective usage: Setting THP to `madvise` allows Oracle to use hugepages only where beneficial, avoiding the downsides of `always` mode.


Oracle-aware optimization: Oracle Database components can now better manage memory and selectively request hugepages, leading to more consistent performance gains.


๐Ÿง  HugePages vs Transparent HugePages

Feature

HugePages (Static)

Transparent HugePages (THP)

Configuration

Manually configured by the system admin

Automatically managed by the kernel

Usage

Reserved explicitly for applications

Kernel tries to use them for anonymous memory

Control

Applications must be configured to use them

Kernel decides when to use them

Swapping

Not swappable (memory stays resident)

Can be swapped unless pinned

Performance

Predictable, stable for large memory apps

May cause latency spikes due to defragmentation

Best for

Oracle SGA, databases, performance-critical apps

General workloads, less admin overhead

Page Allocation

Static allocation at boot time

Dynamic allocation during runtime


What is `clocksource=tsc`?

The `clocksource=tsc` kernel parameter forces Linux to use the Time Stamp Counter (TSC) as the system clock source. Here’s what that means:


• TSC (Time Stamp Counter) is a CPU register that counts cycles since reset. It’s fast and low-overhead.


By default, Linux chooses the most stable and precise clock source available. TSC is often preferred for performance, but only if it’s invariant (i.e., unaffected by CPU frequency scaling or power-saving modes).


Using `clocksource=tsc` can improve performance in latency-sensitive environments like databases or real-time systems, especially when:

•The hardware supports invariant TSC.

• You want consistent timing across CPUs in multi-core systems.

• You’re running Oracle or other performance-critical workloads.


๐Ÿ’ก Why use it? It minimizes overhead and improves timestamp precision, which is crucial for Oracle diagnostics and wait event analysis.


 Why install Oracle 26ai?

Oracle Database 26ai is Oracle’s AI-first long-term support release, packed with over 300 new features. Here’s why it’s worth installing:


Key Benefits:


• AI Integration at the Core: Native support for AI vector search, bringing AI directly to your data without external systems.

• Annotations & Metadata Enhancements: Easier documentation and tracking of database objects.

• Interval Aggregation: New support for `SUM` and `AVG` on `INTERVAL` datatypes.

• Autonomous Options: Can be deployed via Autonomous DB containers or free-tier cloud options.

• Future-Proofing: It’s the next long-term release after 19c, meaning extended support and stability for years.


Ideal Use Cases:

• AI-powered analytics

• High-performance transactional systems

• Cloud-native or hybrid deployments

• Modernizing legacy Oracle environments



Alireza Kamrani 

Optimizing Composite Indexes in Oracle

Optimizing Composite Indexes in Oracle: Balancing Selectivity and Index Skip Scan How to Decide the Leading Column Order in Oracle Composite...