A generated column indexes a field inside JSON

A JSON column cannot be indexed directly, so a query filtering on something inside it scans the table. A generated column extracts the value into a real column that can carry an index, and MySQL keeps it in step.

ALTER TABLE events
  ADD COLUMN customer_id INT
    GENERATED ALWAYS AS (payload->>'$.customer_id') STORED,
  ADD INDEX idx_customer (customer_id);

SELECT * FROM events WHERE customer_id = 91;   -- uses the index

STORED writes the value to disk and can be indexed; VIRTUAL computes it on read and — in 5.7 — can also be indexed, at the cost of computing it during the index build. The column cannot be written to directly, which is the point: there is exactly one source of truth and the extract cannot drift from it. Adding one is an ALTER that rebuilds the table, so it wants the same care as any other schema change on a large table.