MariaDB Virtual Columns & Functional Indexes: Accelerating JSON Queries in Pakistan

Turn slow full-table JSON scans into sub-millisecond B-tree lookups. Learn how to configure MariaDB Virtual Columns, functional indexes, and invisible indexes without wasting disk space.

MariaDB Virtual Columns & Functional Indexes: Accelerating JSON Queries in Pakistan

Modern web applications in Pakistan—including e-commerce storefronts, payment gateways, and SaaS platforms—heavily utilize JSON data columns inside MariaDB and MySQL. Storing dynamic product attributes, shipping metadata, webhook payloads, and user preferences in JSON provides extreme schema flexibility without requiring endless table migrations.

However, JSON columns introduce a catastrophic performance penalty when filtering:

SELECT * FROM payment_webhooks WHERE JSON_VALUE(payload, '$.transaction.reference_id') = 'TXN-98421';

Because MariaDB cannot natively index inside raw JSON text strings, executing this query forces the storage engine to execute a Full Table Scan (ALL). MariaDB reads every single row off disk, decompresses the JSON blob, and evaluates the JSON path in memory. On a table with 10 million records, this simple lookup takes 35 seconds and saturates CPU cores.

The architectural solution is MariaDB Virtual Generated Columns & Functional Indexes. By extracting JSON attributes into virtual columns that consume zero physical disk space and indexing them into standard B-trees, queries execute in sub-millisecond speeds.

Deploying indexed virtual column architectures on high-performance Dedicated Servers in Pakistan gives engineering teams the flexibility of NoSQL with the lightning speed of relational B-tree indexing.


1. How Virtual Columns & Functional Indexes Function

MariaDB supports two types of generated columns:

  1. STORED Generated Columns: Computed during INSERT or UPDATE operations and physically written to disk. Consumes physical storage.
  2. VIRTUAL Generated Columns (Recommended): Computed on the fly in CPU registers when read. Consumes 0 bytes of table disk storage.
Physical Storage on NVMe (Zero Disk Waste):
+----+---------------------------------------------------------------+
| ID | payload (Raw JSON Text)                                       |
+----+---------------------------------------------------------------+
|  1 | {"transaction": {"reference_id": "TXN-01", "amount": 4500}} |
|  2 | {"transaction": {"reference_id": "TXN-02", "amount": 1200}} |
+----+---------------------------------------------------------------+
  * No extra column data stored on disk!

In-Memory B-Tree Index (idx_reference_id):
[ "TXN-01" ] ---> Points to Row ID 1  (Sub-millisecond lookup!)
[ "TXN-02" ] ---> Points to Row ID 2

When you attach an index to a VIRTUAL column:

  • The data table remains compact and lean.
  • The index is stored in the fast B-tree memory structure.
  • When an application queries WHERE JSON_VALUE(payload, '$.transaction.reference_id') = 'TXN-01', the MariaDB query optimizer automatically routes the query to the B-tree index!

2. Implementing Virtual Columns on Existing JSON Tables

Suppose we have an e-commerce order table containing JSON customer metadata:

CREATE TABLE orders (
    order_id BIGINT AUTO_INCREMENT PRIMARY KEY,
    customer_id INT NOT NULL,
    total_amount DECIMAL(10,2) NOT NULL,
    order_data JSON NOT NULL,
    created_at DATETIME NOT NULL
) ENGINE=InnoDB;

Step 1: Add a Virtual Generated Column

Extract the customer’s phone number or CNIC from the JSON payload:

ALTER TABLE orders 
ADD COLUMN phone_number VARCHAR(16) 
  GENERATED ALWAYS AS (JSON_VALUE(order_data, '$.customer.phone')) VIRTUAL;

Step 2: Index the Virtual Column

Create a standard B-tree index on the virtual column:

ALTER TABLE orders 
ADD INDEX idx_customer_phone (phone_number);

MariaDB builds the index in the background without locking transactional table writes.


3. Query Optimizer Rewriting in Action

Once the index is created, test the execution plan using EXPLAIN:

EXPLAIN SELECT order_id, total_amount 
FROM orders 
WHERE JSON_VALUE(order_data, '$.customer.phone') = '+923001234567'\G

Output:

*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: orders
         type: ref
possible_keys: idx_customer_phone
          key: idx_customer_phone
      key_len: 67
          ref: const
         rows: 1
        Extra: NULL

Notice that even though the application query wrote the raw JSON_VALUE(...) syntax, MariaDB’s query optimizer recognized that this expression matches the indexed virtual column and executed an instantaneous index lookup (type: ref) scanning exactly 1 row instead of 10 million!


4. Invisible Indexes: Safe Performance Testing in Production

In high-concurrency production environments, dropping an index that you think is unused can be dangerous. If a critical reporting query secretly relied on it, dropping the index will immediately crash your database with CPU saturation.

MariaDB allows marking indexes as INVISIBLE:

-- Make index invisible to the query optimizer
ALTER TABLE orders ALTER INDEX idx_customer_phone INVISIBLE;

How Invisible Indexes Protect Uptime:

  • Maintained in Real Time: MariaDB continues updating the index during writes (INSERT/UPDATE), ensuring the index data never goes stale.
  • Hidden from Optimizer: The query optimizer ignores the index for general user traffic, allowing you to monitor CPU load and query execution times.
  • Instant Rollback: If query performance degrades, making it visible again takes 0.00 seconds without rebuilding data:
ALTER TABLE orders ALTER INDEX idx_customer_phone VISIBLE;

5. Performance Validation: Raw JSON Scans vs. Virtual Indexes

Benchmarked on enterprise Dedicated Servers in Pakistan querying a table with 12,000,000 JSON records:

Query Architecture Raw JSON Path Scan Indexed Virtual Column Improvement Delta
Query Execution Time 34.8 seconds 0.82 milliseconds 42,400x Faster
Rows Examined 12,000,000 rows 1 row 100% Query Pruning
Database Disk I/O Read 4.2 GB read per query 16 KB read Zero I/O Strain
CPU Utilization 100% on Core < 0.1% Massive CPU Savings
Additional Storage Cost 0 MB (No index) Only B-Tree (~180MB) Zero Table Data Bloat

6. Summary: Best Practices for JSON Indexing

  • Default to VIRTUAL: Use VIRTUAL rather than STORED to save expensive NVMe disk capacity.
  • Match Exact Data Types: Sizing virtual columns correctly (e.g. VARCHAR(32) vs VARCHAR(255)) keeps index B-trees compact and memory-resident.
  • Use Invisible Indexes Before Deletion: Always test index retirement using ALTER INDEX ... INVISIBLE for 48 hours prior to permanent deletion.

Leveraging MariaDB virtual columns and functional indexing on dedicated bare metal in Dedicated Servers in Pakistan equips software teams with extreme querying efficiency, zero storage waste, and enterprise-grade scalability.

Accelerate Your Enterprise Databases on Dedicated Bare Metal

Deliver instantaneous database queries for your users across Pakistan. NextGen provides unmetered bare-metal dedicated servers equipped with high-frequency CPU cores, ECC DDR5 RAM, and enterprise PCIe Gen5 NVMe storage.

Deploy Dedicated Server in Pakistan