索引简单来说是排好序的数据结构,所以它能大幅度的提高查询效率,降低数据排序的成本,降低数据库的IO成本。
但是索引也同样占用很大空间,通常是以索引文件的形式存储在磁盘上,并且更新数据的同时得更新相应的索引。
总的来说:索引能提高查询效率,但降低更新效率,所以经常更新的表尽量不要加索引
一张表建议建立索引不要超过五个
一般来说复合索引优于单值索引
MySql自带的查询优化器,MySql有专门负责优化SELECT语句的优化器模块。
使用EXPLAIN关键字可以模拟优化器执行SQL查询语句,从而知道MySql是如何处理你的SQL语句,从中得出如何优化你的SQL语句。
在SQL语句前+EXPLAIN关键字(如:explain select * from userdb)
CREATE TABLE IF NOT EXISTS blogs(
id INT(10) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
author_id INT(10) UNSIGNED NOT NULL,
category VARCHAR(20) NOT NULL,
views INT(20) NOT NULL,
assist INT(20) NOT NULL,
comments VARCHAR(20) NOT NULL,
title VARCHAR(255) NOT null,
content TEXT NOT NULL);
INSERT INTO blogs(author_id,category,views,assist,comments,title,content)VALUES
(1,'java',821,100,'1','java','1'),
(2,'sql',534,100,'2','sql','1'),
(3,'c',1928,100,'3','c','1'),
(4,'c++',851,100,'4','c++','1'),
(5,'c#',89,50,'5','c#','1');
EXPLAIN SELECT id, author_id from blogs where comments = '1' and views > 1 ORDER BY assist desc LIMIT 1;
show index from blogs;
这里只有sql自主建的主键索引
create index idx_blogs_cva on blogs (comments,views,assist);
show index from blogs
EXPLAIN SELECT id, author_id from blogs where comments = '1' and views > 1 ORDER BY assist desc LIMIT 1;
这里很明显已经用到了索引,但是Extra里面出现了Using filesort,SQL需要优化
Drop index idx_blogs_cva on blogs;
create index idx_blogs_ca on blogs(comments,assist);
EXPLAIN SELECT id, author_id from blogs where comments = '1' and views > 1 ORDER BY assist desc LIMIT 1;
CREATE TABLE IF NOT EXISTS class(
class_id INT(10) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
class_card INT(20) UNSIGNED NOT NULL
);
CREATE TABLE IF NOT EXISTS book(
book_id INT(10) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
book_card INT(20) UNSIGNED NOT NULL
);
INSERT INTO book(book_card) VALUES(FLOOR(1+(RAND()*10)));
INSERT INTO book(book_card) VALUES(FLOOR(1+(RAND()*10)));
INSERT INTO book(book_card) VALUES(FLOOR(1+(RAND()*10)));
INSERT INTO book(book_card) VALUES(FLOOR(1+(RAND()*10)));
INSERT INTO book(book_card) VALUES(FLOOR(1+(RAND()*10)));
INSERT INTO book(book_card) VALUES(FLOOR(1+(RAND()*10)));
INSERT INTO book(book_card) VALUES(FLOOR(1+(RAND()*10)));
INSERT INTO book(book_card) VALUES(FLOOR(1+(RAND()*10)));
INSERT INTO book(book_card) VALUES(FLOOR(1+(RAND()*10)));
INSERT INTO book(book_card) VALUES(FLOOR(1+(RAND()*10)));
EXPLAIN SELECT * FROM book RIGHT JOIN class ON class_card = book_card;
ALTER TABLE book ADD INDEX idx_book_c (book_card);
EXPLAIN SELECT * FROM book RIGHT JOIN class ON class_card = book_card;
ALTER TABLE class ADD INDEX idx_class_c (class_card);
EXPLAIN SELECT * FROM book RIGHT JOIN class ON class_card = book_card;
-删除book索引,再用EXPLAIN
DROP index idx_book_c on book;
EXPLAIN SELECT * FROM book RIGHT JOIN class ON class_card = book_card;
很明显效率不如添加book表的索引好
总结一下:right join (右连接) ,用左表建索引效果高于右表,left join (左连接) 同理,即:与连接相对的表建立索引效果较好。 尽量用小结果集驱动大结果集(如右连接,就是左表驱动右边,在左表建立索引的效果要好于右表)。
CREATE TABLE students(
id INT(10) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(20) NOT NULL,
age INT(10) UNSIGNED NOT NULL DEFAULT 0,
grade INT(10) UNSIGNED NOT NULL DEFAULT 0,
pos VARCHAR(20) DEFAULT ''
);
INSERT INTO students(name,age,grade,pos) VALUES ('zs',20,97,'monitor');
INSERT INTO students(name,age,grade,pos) VALUES ('ls',22,74,'committee');
INSERT INTO students(name,age,grade,pos) VALUES ('ww',21,100,'committee');
INSERT INTO students(name,age,grade,pos) VALUES ('mw',21,59,'personal');
INSERT INTO students(name,age,grade,pos) VALUES ('zl',21,87,'personal');
ALTER TABLE students ADD INDEX idx_students_nap (name, age, pos);
EXPLAIN SELECT * FROM students WHERE name='zs';
EXPLAIN SELECT * FROM students WHERE name='zs' AND age=20;
EXPLAIN SELECT * FROM students WHERE name='zs' AND age=20 AND pos='monitor';
很明显,三条语句依次是增加了精度,同时key_len也增加,但是都用到了索引
现在看看索引失效的情况:
EXPLAIN SELECT * FROM students WHERE age=20 AND pos='monitor';
EXPLAIN SELECT * FROM students WHERE pos='monitor';
EXPLAIN SELECT * FROM students WHERE age=20;
由此得出:查询应从索引的最左前列开始并且不跳过索引中的列(即最佳左前缀法则)