Índice MySQL, sintaxe, regras de índice, falha de índice (dez regras)

​​Este artigo é de Recent Zhu Zhu, criado a partir de Recent Zhu Zhu. Indique a fonte para reimpressão.

O que é um índice:

1. A essência do conceito -> a tabela de índice formada pela combinação da linha DB_ID após a classificação de acordo com o campo de índice. Função -> Definir índices razoavelmente pode melhorar muito a eficiência da consulta. Nota -> Se o índice está ativado ou não está relacionado às regras do mecanismo de pesquisa, que estão diretamente relacionadas à ordem lógica dos scripts SQL.

2. Classificação

聚集索引(InnoDB)-> 索引和数据同在(定位索引即查找到数据)	  一张表只能有一个聚集索引(物理排序)
    
非聚集索引(MYISAM)-> 索引和数据分离(定位索引后需要返表获取)	一张表可以有多个聚集索引
    
经验-> MySql表设计 保留自增列主键字段
	主键为 集聚索引且唯一 保证查询效率
	自增列 避免添加数据而产生数据重排

3. Princípio

B树 -> 节点中可以容纳多个数据(等于Max_Degree 将第二个数据独立节点引出) 有利于降低树的高度 
B+树 ->引入双向链表(范围查询)并配合数据冗余(空间换时间) 合理解决范围查询的需求
    

O índice que entendo é: uma pesquisa regular, não uma pesquisa aleatória, classificar as coisas que você precisa encontrar e obter o que queremos de acordo com suas necessidades. A tabela gerada por essa classificação é chamada de índice, também conhecida como tabela de índice , mas essa regra também é condicional em vez de um arranjo imaginário, e é por isso que o índice falhará

sintaxe do índice

Índice clusterizado (InnoDB) -> Adicionar chave primária ALTER TABLE tabela ADD PRIMARY KEY tabela (coluna)

Índice não clusterizado (InnoDB ou MYISAM)

	普通索引 -> CREATE INDEX 索引名 ON 表(列)	
	唯一索引 -> CREATE UNIQUE INDEX 索引名 ON 表(列)
	组合索引 -> CREATE INDEX 索引名 ON 表(列1,列2)
	函数索引 -> CREATE INDEX 索引名 ON 表(函数(列))

Excluir índice -> DROP INDEX nome do índice na tabela

EXPLICAR SELECIONAR...

	*type->查询分类* 
            
			const -> 等值查询
			ref   -> 引用查询
			index -> 索引查询
			range -> 范围查询
			ALL   -> 全部查询
                            
	
	*key->启用索引 | NULL 索引失效*

regras de índice

1) O negócio de consulta não envolve muita filtragem de dados -> não é recomendado criar índices 2) Não crie mais de cinco índices em uma tabela 3) Não crie mais de cinco campos de índice combinados 4) Crie índices em colunas com comprimentos de campo menores, tanto quanto possível

	对于字符串 
		CHAR(可以) 
		VARCHAR(考虑) 
		TEXT(不推荐)
	对于数字 
		INT 转化 TINYINT -> 大小够用
		FLOAT 转化 INT	 -> 如果保留两位小数 乘以100 用INT类型
	对于日期
		DATETIME(8字节) 转化为 TIMESTAMP(4字节)
                    

5) A taxa de repetição dos dados da coluna é muito alta e não há necessidade de criar um índice

	eg:性别

6) Considere a coluna de consulta para criar um índice composto razoavelmente (maior eficiência do que o índice de coluna única)

Invalidação de índice (regras de dez)

索引-> CREATE INDEX idx_name_sal_date ON emp(ename,sal,hiredate);

1) Verificação completa da tabela -> não envolve filtragem condicional

	所有查询字段都有索引(有效) -> index
	eg:EXPLAIN SELECT empno,ename,sal,hiredate FROM emp;
	
	条件(索引列表左匹配原则)等值(有效) -> ref
	EXPLAIN SELECT empno,ename,sal,hiredate,job FROM emp WHERE ename='SCOTT';

	条件范围(失效) -> range
	EXPLAIN SELECT empno,ename,sal,hiredate,job FROM emp WHERE sal > 0;

compreensivo:

  1. Existe um índice para localizar todas as páginas com índices. Se uma coluna não indexada for adicionada à coluna pesquisada, a consulta não terá índice.
  2. Uma coluna não indexada na condição de pesquisa também tornará a consulta não indexada.
  3. Se as colunas de pesquisa forem todas indexadas, elas serão consultas indexadas, independentemente das condições
  4. A consulta segue o princípio de correspondência à esquerda. Se a consulta não tiver a coluna à esquerda do índice, a pesquisa também será uma pesquisa não indexada
  5. 字符串where条件后,>符号存在索引,<不存在索引
  6. 最左匹配,只有匹配最左边一个就OK,后面的不管为啥,此次查询都为索引查询
  7. 数字隐式转换,为列匹配一个不属于他的数据类型
  8. 范围或者等值查询不符合最左匹配则已定位非索引查询
  9. range(范围查找)可能引起失效,也可能不失效,当范围查找的值在索引里时他有效,而值不在里面时则无效,没有固定的规则

2)全列扫描 -> 全字段匹配

	有一个非索引字段(失效) ->ALL
	eg:EXPLAIN SELECT empno,ename,sal,hiredate,job FROM emp;
	
            

3)!= <>

	eg:EXPLAIN SELECT empno,ename,sal,hiredate,job FROM emp WHERE ename!='SCOTT';
	

4)NOT NULL

	eg:EXPLAIN SELECT empno,ename,sal,hiredate,job FROM emp WHERE ename IS NOT NULL;
	

5)函数处理

	eg:EXPLAIN SELECT empno,ename,sal,hiredate,job FROM emp WHERE CHAR_LENGTH(ename) = 5;
	

6)模糊查询 % 开头

	eg:EXPLAIN SELECT empno,ename,sal,hiredate,job FROM emp WHERE ename LIKE '%a';
	

7)OR 关键字

	eg:EXPLAIN SELECT empno,ename,sal,hiredate,job FROM emp WHERE ename = 'SCOTT' OR sal = 0;
	

8)等值判断左匹配

	eg:EXPLAIN SELECT empno,ename,sal,hiredate,job FROM emp WHERE sal = 0 AND hiredate = '2000-1-1 0:00:00';
	

9)范围查询右忽略

	eg:EXPLAIN SELECT empno,ename,sal,hiredate,job FROM emp WHERE ename > 'SCOTT' AND sal = 0; (有效 range)
	eg:EXPLAIN SELECT empno,ename,sal,hiredate,job FROM emp WHERE ename > 'aaa' AND sal = 0; (失效 ALL)

10)数字隐式转换 -> 字符串数字缺失引号

	EXPLAIN SELECT empno,ename,sal,hiredate,job FROM emp WHERE ename = 10

代码解析:

-- 建立组合索引
CREATE INDEX ON idex_name_sal_hiredate FROM emp(ename,sal,hiredate);

-- 十种索引失效测试
-- 第一种
-- 条件范围失效
EXPLAIN SELECT empno,ename,sal,hiredate ,job FROM emp WHERE sal>0;


-- 等值查询有效(左匹配原则,)--ref
EXPLAIN SELECT empno,ename,sal,hiredate,job FROM emp WHERE ename='scott' AND sal=0;


-- 查询所有字段都有索引(有效) --index
EXPLAIN SELECT empno,ename,sal,hiredate FROM emp ;


-- 第二种(全字段匹配,全文扫描)
-- 存在非索引字段
-- 失效 
EXPLAIN SELECT empno,ename,sal,hiredate,job FROM emp; 

-- 第三种,不对等号,!=,<>(这个也遵循左匹配原则)(失效)
EXPLAIN SELECT empno,ename,sal,hiredate,job FROM emp WHERE ename <> 'scott';

EXPLAIN SELECT empno,ename,sal,hiredate,job FROM emp WHERE  ename !='scott';


-- >尝试 (有效)--range
EXPLAIN SELECT empno,ename,sal,hiredate,job FROM emp WHERE ename>'scott';



-- < 尝试(无效)
EXPLAIN SELECT empno,ename,sal,hiredate,job FROM emp WHERE ename<'scott';


-- = 尝试()--ref(索引查找)(必须符合最左匹配原则,否则也无效)
-- 最左匹配原则,必须先从左边开始匹配,否则无效
EXPLAIN SELECT empno,ename,sal,hiredate,job FROM emp WHERE ename>'scott';


-- 无效  sal>0
EXPLAIN SELECT empno,ename,sal,hiredate,job FROM emp WHERE sal>0;


-- 无效 hiredate>'2021-08-31 18:23:55'
EXPLAIN SELECT empno,ename,sal,hiredate,job FROM emp WHERE hiredate>'2021-08-31 18:23:55';

-- 最左匹配原则 有效 -- range ename>'scott' AND sal>0
EXPLAIN SELECT empno,ename,sal,hiredate,job FROM emp WHERE ename>'scott' AND sal>0 ;

-- 最左匹配,只有匹配最左边一个就OK,后面的不管为啥,次查询都为索引查询
EXPLAIN SELECT empno,ename,sal,hiredate,job FROM emp WHERE ename>'scott' AND hiredate<'2021-08-31 18:23:55' ;


-- 第四种 is not null (无效)
EXPLAIN SELECT empno,ename,sal,hiredate,job FROM emp WHERE ename IS NOT NULL;
-- is null (有效)-- ref(索引查询)
EXPLAIN SELECT empno,ename,sal,hiredate,job FROM emp WHERE ename IS NULL ;




-- 第五种(函数处理)
-- 函数--》 数字函数,字符串函数,日期函数(无效)
EXPLAIN SELECT empno,ename,sal,hiredate,job FROM emp WHERE CHAR_LENGTH(ename) ;

-- 第六种 (模糊查询,使用%开头)(无效)
EXPLAIN SELECT empno,ename,sal,hiredate,job FROM emp WHERE ename LIKE '%a' ;

-- 不以%开头(有效)-- range(范围查询)
EXPLAIN SELECT empno,ename,sal,hiredate,job FROM emp WHERE ename  LIKE 'a%' ;


-- 第七种  or关键字(无效)
EXPLAIN SELECT empno,ename,sal,hiredate,job FROM emp WHERE ename='sctto' OR sal=0 ;



-- 第八种  等值判断最左匹配(and,最左匹配)(无最左值,无效)
EXPLAIN SELECT empno,ename,sal,hiredate,job FROM emp WHERE sal = 0 AND hiredate = '2000-1-1 0:00:00' ;



-- 第九种 范围查询右忽略
-- 最左查询无效(前提),则也不考虑右查询了
-- range(范围查询)(可能会引起失效)如下
-- (有效) -- range(范围查询)
-- 查找范围值在范围里时,则有效
 EXPLAIN SELECT empno,ename,sal,hiredate,job FROM emp WHERE ename>'sctto' AND sal=0 ;
 EXPLAIN SELECT empno,ename,sal,hiredate,job FROM emp WHERE ename>'sctto' AND sal>0 ;
 EXPLAIN SELECT empno,ename,sal,hiredate,job FROM emp WHERE ename>'sctto';


-- (无效)
EXPLAIN SELECT empno,ename,sal,hiredate,job FROM emp WHERE ename>'aaa' AND sal=0 ;
EXPLAIN SELECT empno,ename,sal,hiredate,job FROM emp WHERE ename>'aaa';




-- 第十种 数字隐式转换
-- 字段为string给他匹配一个int则存在一个隐式转换 (无效)
EXPLAIN SELECT empno,ename,sal,hiredate,job FROM emp WHERE ename= 10;

-- 匹配一个符合自己数据类型,却不存在的值(有效) -- ref(索引查询)
EXPLAIN SELECT empno,ename,sal,hiredate,job FROM emp WHERE ename='10';

SQL优化(所有的部分查询(子查询)都为索引查询)

作用 ->处理"慢查询" 用户体验度 程序反馈时间三秒以内 要求查询效率控制在0.5秒以内 注意 ->最后结果一定通过实际数据测试完成

1) != <>

	SELECT empno,ename,sal,hiredate,job FROM emp WHERE ename!='SCOTT'; 
	
	--> 半优化
	SELECT empno,ename,sal,hiredate,job FROM emp WHERE ename > 'SCOTT'	
	UNION
	SELECT empno,ename,sal,hiredate,job FROM emp WHERE ename < 'SCOTT'	
	
	-->	全优化
	SELECT empno,ename,sal,hiredate,job FROM emp WHERE empno <> 
	(SELECT empno FROM emp WHERE ename = 'SCOTT')
	

2) OR

	SELECT empno,ename,sal,hiredate,job FROM emp WHERE ename = 'SCOTT' OR sal = 800
	
	-->
	SELECT empno,ename,sal,hiredate,job FROM emp WHERE ename = 'SCOTT'
	UNION
	SELECT empno,ename,sal,hiredate,job FROM emp WHERE sal = 800
	
	-->
	SELECT empno,ename,sal,hiredate,job FROM emp WHERE ename = 'SCOTT'
	UNION
	SELECT empno,ename,sal,hiredate,job FROM emp WHERE empno = 
	(SELECT empno FROM emp WHERE sal = 800)
	

3) 表联接效率高于子查询

	SELECT ename,dname FROM emp LEFT JOIN dept ON emp.DEPTNO = dept.DEPTNO 
	
	SELECT ename,(SELECT dname FROM dept WHERE emp.DEPTNO = dept.DEPTNO) dname FROM emp
	

4) 表联接数量不要超过三张 最好控制在两张

	表联接比较复杂 考虑添加数据冗余 -> 空间换时间
	

5) 尽量避免全表扫描 即便存在也要进行分页

6) 分页(****) 越靠后的数据查询效率越低**

	SELECT empno,ename,sal from emp LIMIT 100000,10
	
	SELECT empno,ename,sal,job FROM emp 
	WHERE empno > (SELECT empno FROM emp LIMIT 10000,1)
	AND empno < (SELECT empno FROM emp LIMIT 10010,1);

7) 杜绝使用 * 根据需求 填写必要的列

8) 模糊查询

	开头匹配 "A%" 
	结尾匹配 表中添加反转列 使用反转列匹配 "A%"
	

9) 函数处理

	参照结尾匹配处理过程 添加函数结果列 并设置索引
	

10)NoSql数据库进行有力的支撑

	Redis 
	

代码实现:

-- sql优化 (可用explaoin查看索引)
-- 1:!= <> 

-- 查询不叫Scott的员工信息
-- 非优化
SELECT empno,ename,sal,hiredate,job FROM emp WHERE ename != "SCOTT";

SELECT empno,ename,sal,hiredate,job FROM emp WHERE ename <>'scott';


-- 优化
SELECT empno,ename,sal,hiredate,job FROM emp WHERE empno <>
(SELECT empno FROM emp WHERE ename='scott');

-- 半优化
SELECT empno,ename,sal,hiredate,job FROM emp WHERE ename >'scott'
UNION 
SELECT empno,ename,sal,hiredate,job FROM emp WHERE ename <'scott';

-- 2:or
-- 查找员工名字叫scott工资或者800的员工
-- 非优化
SELECT empno,ename,sal,hiredate,job FROM emp WHERE ename='scott' OR sal='800';


-- 优化
SELECT  empno,ename,sal,hiredate,job FROM emp WHERE ename='scott'
UNION 
SELECT  empno,ename,sal,hiredate,job FROM emp WHERE sal = '800'; 

-- 优化
SELECT  empno,ename,sal,hiredate,job FROM emp WHERE ename='scott'
UNION
 empno,ename,sal,hiredate,job FROM emp WHERE empno =
 (SELECT empno FROM emp WHERE sal=800);

-- 3:表联接
-- 员工对应部门
-- 优化
SELECT ename,dname FROM emp LEFT JOIN dept ON emp.deptno=dept.deptno;

-- 优化
USE mytest;
SELECT ename,(SELECT dname FROM dept WHERE emp.deptno=dept.deptno) dname FROM emp;


-- 4:表联接的数量不要超过三张,最好控制在两张



-- 5:尽量避免全表扫描,即便存在也要进行分页

-- 6:分页越靠后的数据查询效率越低

-- 查询10万条数据最后十行
-- 非优化
SELECT  empno,ename,sal FROM emp LIMIT 100000,10;

-- 优化
SELECT empno,ename,sal FROM emp 
WHERE empno>(SELECT empno FROM emp LIMIT 100000,1)
AND empno <(SELECT empno FROM emp LIMIT 100010,1);


-- 7:杜绝使用* 根据需求 填写必要的列

-- 8:模糊查询
	-- 开头匹配 "A%"
	-- 结尾匹配 表中添加反转列 ,使用反转列"A%"
	
	

-- 9:函数处理
-- 根据函数处理,生成一个函数结果列,并设置索引,查找根据新列查找


-- 10:nosql数据库进行有力支撑
-- Redis


索引重点:sql优化

end》》》

生活要永远清醒,永远温柔,永远知进退,慢慢走,沿途有风景,背后亦有阳光。不鸣则已,一鸣惊人-- 司马迁

Acho que você gosta

Origin juejin.im/post/7220643710659657785
Recomendado
Clasificación