====== mysql:index:composite ====== * **What it is:** A composite index is an index that contains multiple columns in a specific order, e.g. (user_id, status, created_at). * **What it’s for:** Speed up queries that filter/sort by those columns, especially when the query uses the leftmost columns first. * **Key rule (leftmost prefix):** * If your index is (A, B, C), it helps queries using: * (A) * (A, B) * (A, B, C) * It usually does **NOT** help as much if you only filter by (B) or (C) without (A). * **Example (table):** CREATE TABLE orders ( id BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT, user_id BIGINT UNSIGNED NOT NULL, status VARCHAR(20) NOT NULL, created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ); * **Example (create composite index):** CREATE INDEX idx_orders_user_status_created ON orders (user_id, status, created_at); * **Example (queries that benefit):** -- Uses (user_id, status, created_at) SELECT * FROM orders WHERE user_id = 10 AND status = 'paid' ORDER BY created_at DESC LIMIT 50; -- Uses leftmost prefix (user_id) SELECT * FROM orders WHERE user_id = 10 ORDER BY created_at DESC LIMIT 50; -- Uses (user_id, status) even without ordering SELECT COUNT(*) FROM orders WHERE user_id = 10 AND status = 'paid'; * **Example (query that may NOT benefit much):** -- Missing leftmost column (user_id) SELECT * FROM orders WHERE status = 'paid' ORDER BY created_at DESC; * **How to verify (EXPLAIN):** EXPLAIN SELECT * FROM orders WHERE user_id = 10 AND status = 'paid' ORDER BY created_at DESC LIMIT 50; * **Common mistakes:** * Putting low-selectivity columns first (e.g. status) can reduce usefulness. * Creating too many indexes slows down INSERT/UPDATE/DELETE. * **Vocabulary (hard words):** * **composite** /kəmˈpɑː.zɪt/ — composite (kết hợp) * **selectivity** /sɪˌlek.tɪˈvɪt.i/ — selectivity (độ phân biệt / mức “lọc” tốt) * **prefix** /ˈpriː.fɪks/ — prefix (tiền tố) * **verify** /ˈver.ɪ.faɪ/ — verify (xác minh) * **slow down** /sloʊ daʊn/ — slow down (làm chậm)