MySQL Unique Indexes
Unique indexes are a powerful feature in MySQL that serve two crucial purposes: they enforce data uniqueness while also potentially improving query performance. If you're building applications that require data integrity (and most do), understanding unique indexes is essential.
What is a Unique Index?
A unique index ensures that the indexed columns do not store duplicate values. It acts as both a constraint and a performance optimization tool.
Unlike regular indexes which only speed up queries, unique indexes also enforce a business rule: the values in the indexed column(s) must be unique across all rows in the table.
Key characteristics:
- Prevents duplicate entries in the specified column(s)
- Can include single or multiple columns (composite unique indexes)
- Allows NULL values (though only one NULL in MySQL)
- Improves query performance when searching by the indexed column(s)
- Is automatically created when you define a UNIQUE constraint or PRIMARY KEY
Creating Unique Indexes
There are several ways to create unique indexes in MySQL:
Method 1: During Table Creation
CREATE TABLE customers (
customer_id INT AUTO_INCREMENT,
email VARCHAR(100),
phone VARCHAR(15),
PRIMARY KEY (customer_id),
UNIQUE INDEX idx_email (email),
UNIQUE INDEX idx_phone (phone)
);
Method 2: Adding to an Existing Table
ALTER TABLE customers
ADD UNIQUE INDEX idx_email (email);
Method 3: Using CREATE INDEX Statement
CREATE UNIQUE INDEX idx_phone
ON customers (phone);
Composite Unique Indexes
Sometimes uniqueness needs to be enforced across a combination of columns:
CREATE TABLE order_items (
order_id INT,
product_id INT,
quantity INT,
PRIMARY KEY (order_id, product_id),
UNIQUE INDEX idx_order_product (order_id, product_id)
);
In this example, the combination of order_id
and product_id
must be unique, preventing the same product from being added to the same order multiple times.
Unique Indexes vs. Primary Keys
While both enforce uniqueness, there are important differences:
Feature | Primary Key | Unique Index |
---|---|---|
NULL values | Not allowed | Allowed (one per column) |
Number per table | Only one | Multiple allowed |
Auto-creates index | Yes | Yes |
Implicit naming | Always PRIMARY | System-generated if not specified |
Practical Example: User Registration System
Let's see unique indexes in action with a user registration system:
-- Create a users table with unique constraints
CREATE TABLE users (
user_id INT AUTO_INCREMENT,
username VARCHAR(50),
email VARCHAR(100),
phone VARCHAR(15),
PRIMARY KEY (user_id),
UNIQUE INDEX idx_username (username),
UNIQUE INDEX idx_email (email),
UNIQUE INDEX idx_phone (phone)
);
-- Insert a user successfully
INSERT INTO users (username, email, phone)
VALUES ('johndoe', '[email protected]', '555-1234');
-- This will succeed (different values)
INSERT INTO users (username, email, phone)
VALUES ('janedoe', '[email protected]', '555-5678');
-- This will fail (duplicate email)
INSERT INTO users (username, email, phone)
VALUES ('johnsmith', '[email protected]', '555-9012');
The last insertion will produce an error:
Error Code: 1062. Duplicate entry '[email protected]' for key 'users.idx_email'
Handling Duplicates: ON DUPLICATE KEY
MySQL provides a useful feature to handle potential duplicates:
INSERT INTO users (username, email, phone)
VALUES ('johnsmith', '[email protected]', '555-9012')
ON DUPLICATE KEY UPDATE
phone = VALUES(phone);
This will update the existing user's phone number instead of failing.
Partial Unique Indexes
In MySQL 8.0+, you can create unique indexes on a subset of rows using a WHERE clause:
CREATE TABLE employees (
emp_id INT AUTO_INCREMENT PRIMARY KEY,
email VARCHAR(100),
status ENUM('active', 'inactive', 'deleted')
);
-- Only enforce uniqueness for active employees
CREATE UNIQUE INDEX idx_active_email
ON employees (email)
WHERE status = 'active';
NULL Values in Unique Indexes
Unique indexes treat NULL values specially - MySQL allows multiple NULL values in a unique index:
CREATE TABLE contacts (
contact_id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
email VARCHAR(100),
UNIQUE INDEX idx_email (email)
);
-- Both inserts will work despite the UNIQUE index
INSERT INTO contacts (name, email) VALUES ('John', NULL);
INSERT INTO contacts (name, email) VALUES ('Jane', NULL);
Performance Implications
Unique indexes have both benefits and costs:
Benefits:
- Improved query performance for searches on indexed columns
- Data integrity enforcement at the database level
- Can be used by the query optimizer for better execution plans
Costs:
- Additional storage space required
- Slower INSERT, UPDATE and DELETE operations
- Maintenance overhead during large data changes
Real-world Use Cases
1. User Authentication Systems
CREATE TABLE accounts (
account_id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL,
email VARCHAR(100) NOT NULL,
password_hash VARCHAR(255) NOT NULL,
UNIQUE INDEX idx_username (username),
UNIQUE INDEX idx_email (email)
);
2. Product Catalog with SKUs
CREATE TABLE products (
product_id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
sku VARCHAR(50) NOT NULL,
category_id INT,
UNIQUE INDEX idx_sku (sku),
INDEX idx_category (category_id)
);
3. Inventory Tracking
CREATE TABLE inventory_locations (
item_id INT,
warehouse_id INT,
location_code VARCHAR(10),
quantity INT NOT NULL DEFAULT 0,
PRIMARY KEY (item_id, warehouse_id),
UNIQUE INDEX idx_location (warehouse_id, location_code)
);
Best Practices for Unique Indexes
-
Name indexes meaningfully: Use prefixes like
idx_
oruidx_
for clarity. -
Be selective: Only create unique indexes when necessary for data integrity.
-
Consider column order: For composite indexes, put the most selective columns first.
-
Watch for NULL values: Remember NULL handling can affect uniqueness enforcement.
-
Monitor performance: Check if indexes are being used and not causing excessive overhead.
-
Be careful with long strings: Consider partial indexing for long text columns.
-
Use with foreign keys: Consider adding unique constraints on columns referenced by foreign keys.
Troubleshooting Unique Index Issues
Finding Duplicate Values Before Creating a Unique Index
SELECT email, COUNT(email)
FROM customers
GROUP BY email
HAVING COUNT(email) > 1;
Analyzing Index Usage
EXPLAIN SELECT * FROM customers WHERE email = '[email protected]';
Checking Existing Indexes
SHOW INDEXES FROM customers;
Summary
Unique indexes are a fundamental feature in MySQL that serve the dual purpose of enforcing data uniqueness and improving query performance. We've covered:
- Creating unique indexes using different methods
- Composite unique indexes for multi-column uniqueness
- Differences between primary keys and unique indexes
- Handling NULL values and duplicates
- Performance implications and best practices
- Real-world applications
By properly implementing unique indexes, you can ensure data integrity while also optimizing the performance of your MySQL database queries.
Additional Resources
- MySQL documentation on CREATE INDEX statements
- Books on MySQL optimization and indexing strategies
- Online courses on database design and MySQL performance tuning
Exercises
- Create a
books
table with a unique ISBN column. - Design a table for a library system where a book can only be borrowed once by a member at a given time.
- Write a query to find potential duplicate email addresses in an existing table.
- Create a unique composite index on a
student_courses
table to ensure a student can't enroll in the same course twice.
If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)