MySQL / Index

Index

Index нь номын ard-ын лавлах хуудас шиг ажилладаг — MySQL хүснэгтийн бүх мөрийг нэг нэгээр шалгахын оронд index ашиглан шуурхай олдог. Том өгөгдлийн санд query хурд шөнө, өдрийн ялгаатай байж болно.

Index яаж ажилладаг вэ?

Index үгүй үед MySQL full table scan хийнэ — бүх мөрийг нэг нэгээр харна. 1 сая мөртэй хүснэгтэд энэ нь удаан.

Index байвал MySQL B-tree бүтэц ашиглан хэдхэн алхмаар зорилтот мөрт хүрнэ.

sql
-- Index үгүй: 1,000,000 мөрийг бүгдийг шалгана
SELECT * FROM users WHERE email = 'bold@example.com';

-- email баганад index байвал: ~20 алхамд олдоно

Жишээ хүснэгт

sql
CREATE TABLE users (
  id         INT PRIMARY KEY AUTO_INCREMENT,
  username   VARCHAR(50)  NOT NULL,
  email      VARCHAR(100) NOT NULL,
  country    VARCHAR(50),
  created_at DATETIME DEFAULT NOW()
);

-- 100,000 мөр оруулах (тест өгөгдөл)

CREATE INDEX — index үүсгэх

sql
-- Энгийн index
CREATE INDEX idx_email ON users (email);

-- Нэрлэхгүй байж болно (MySQL автоматаар нэрлэнэ)
CREATE INDEX ON users (country);

-- Хүснэгт үүсгэхдээ зэрэг
CREATE TABLE products (
  id    INT PRIMARY KEY AUTO_INCREMENT,
  sku   VARCHAR(50),
  name  VARCHAR(200),
  price DECIMAL(10,2),
  INDEX idx_sku (sku)
);

UNIQUE INDEX

sql
-- Давхардал зөвшөөрөхгүй index
CREATE UNIQUE INDEX idx_unique_email ON users (email);

-- Одоо нэг и-мэйл хоёр удаа оруулах боломжгүй
INSERT INTO users (email) VALUES ('bold@example.com');
INSERT INTO users (email) VALUES ('bold@example.com');
-- ERROR 1062: Duplicate entry 'bold@example.com'

PRIMARY KEY нь автоматаар UNIQUE INDEX үүсгэдэг.

Composite index — олон баганын index

sql
-- Хоёр баганын хавсарсан index
CREATE INDEX idx_country_created ON users (country, created_at);

-- Энэ index дараах query-д ашиглагдана:
SELECT * FROM users WHERE country = 'MN';
SELECT * FROM users WHERE country = 'MN' AND created_at > '2025-01-01';

-- Харин энэ query-д АШИГЛАГДАХГҮЙ (эхний багана байхгүй):
SELECT * FROM users WHERE created_at > '2025-01-01';

Composite index нь зүүнээс баруун тийш ажилладаг — эхний баганаар шүүхгүй бол index ажиллахгүй. Энийг leftmost prefix rule гэнэ.

FULLTEXT INDEX

sql
-- Текст хайлтад зориулсан index
CREATE FULLTEXT INDEX idx_content ON articles (title, body);

-- FULLTEXT хайлт
SELECT * FROM articles
WHERE MATCH(title, body) AGAINST('MySQL өгөгдлийн сан');

-- Boolean горим
SELECT * FROM articles
WHERE MATCH(title, body) AGAINST('+MySQL -PostgreSQL' IN BOOLEAN MODE);

LIKE '%текст%' нь index ашиглахгүй. Том текст хайлтад FULLTEXT index хэрэглэх нь зөв.

SHOW INDEX — index харах

sql
-- Хүснэгтийн бүх index жагсаах
SHOW INDEX FROM users;

-- Гаралт:
-- Table | Key_name          | Column_name | Unique | ...
-- users | PRIMARY           | id          | 0      |
-- users | idx_email         | email       | 0      |
-- users | idx_unique_email  | email       | 1      |

Index устгах

sql
DROP INDEX idx_email ON users;

-- PRIMARY KEY устгах
ALTER TABLE users DROP PRIMARY KEY;

Index-ийн сул тал

Index бүх асуудлыг шийддэггүй — зарим тохиолдолд хор хөнөөлтэй:

Write удааширна: INSERT, UPDATE, DELETE хийх бүрт MySQL index-ийг шинэчилдэг. Index олон байвал write үйлдэл удааширна.

sql
-- Хүснэгтэд 5 index байвал:
-- Нэг INSERT → 5 index шинэчлэгдэнэ

Зай эзэлнэ: Index нь дискний зай ашигладаг — заримдаа хүснэгттэй тэнцэх хэмжээний зай.

Дүрэм:

  • WHERE, JOIN ON, ORDER BY дотор байнга хэрэглэгддэг баганад index тавь
  • Өөрчлөлт ихтэй баганад index тавихдаа болгоомжтой
  • Жижиг хүснэгтэд (1000-аас доош мөр) index тус болохгүй

Index хэрэглэж байгаа эсэхийг шалгах

sql
-- EXPLAIN: MySQL query яаж ажиллуулж байгааг харуулна
EXPLAIN SELECT * FROM users WHERE email = 'bold@example.com';

-- type = 'ref' эсвэл 'eq_ref' → index ашиглаж байна ✓
-- type = 'ALL'               → full scan, index ашиглахгүй ✗

EXPLAIN хэрэглэлтийг 31-р хичээлд дэлгэрэнгүй үзнэ.

Дараагийн хичээлд:

View — давтан хэрэглэгддэг query-г хадгалах, хялбарчлах аргыг үзнэ.