MySQL面试题讲解之如何设置Hash索引
作者:该用户快成仙了 发布时间:2024-01-21 17:23:55
除了B-Tree 索引,MySQL还提供了如下索引:
Hash索引
只有Memory引擎支持,场景简单
R-Tree索引
MyISAM的一个特殊索引类型,主要用于地理空间数据类型
Full-text
MyISAM的一个特殊索引,主要用于全文索引,从MySQL 5.6开始InnoDB支持全文索引
索引 / 存储引擎MyISAMInnoDBMemoryB-Tree索引支持支持支持HASH索引不支持不支持支持R-Tree索引支持支持不支持Full-text索引支持支持不支持
最常用的索引也就是B-tree索引和Hash索引,且只有Memory, NDB两种引擎支持Hash索引。 Hash索引适于key-value查询,通过Hash索引比B-tree索引查询更加迅速。但Hash索引不支持范围查找例如<><==,>==等。 Memory只有在"="的条件下才会使用hash索引
MySQL在 8.0才支持函数索引,在此之前只能对列的前面某一部分进行索引,例如标题title字段,可以只取title的前10个字符索引,这样的特性大大缩小了索引文件的大小,但前缀索引也有缺点,在order by和group by操作时失效。
create index idx_title on film(title(10));
1 特点
只存在数组,用一个hash函数把key转换成一个确定的内存位置,然后把value放在数组的该位置。使用 hash 自然会有哈希冲突可能,MySQL 采取拉链法解决。
Hash索引基于Hash表实现,只有查询条件精确匹配Hash索引中的列时,才能够使用到hash索引。对于Hash索引中的所有列,存储引擎会为每行计算一个hashcode,Hash索引中存储的就是hashcode。
例如一个维护了身份证号和姓名的表,根据身份证号查找对应名字,其hash索引如下:
比如我们想查ID_card_n4对应username:
将ID_card_n4通过hash函数算出A
按顺序遍历,找到User4
四个ID_card_n值并不一定递增,这样即使增加新的User,速度也快,只需在后追加。 当然缺点也很明显,不是有序,所以hash索引做区间查询速度很慢。比如要找身份证号在[ID_card_X, ID_card_Y]区间的所有用户,就须全表扫描。
2 Hash索引的缺陷
必须二次查找
不支持部分索引查找、范围查找
哈希码可能存在哈希冲突,如果hash 算法设计不好,碰撞过多,性能也会变差
索引存放的是hash值,所以仅支持 < = > 以及 IN
无法通过操作索引来排序,因为存放的时候会经过hash计算,但是计算的hash值和存放的不一定相等,所以无法排序
不能避免全表扫描,只是由于在memory表里支持非唯一值hash索引,即不同的索引键,可能存在相同hash值
因为哈希表是一种根据关键字直接访问内存存储位置的数据结构 ,所以利用其原理的hash 索引,也就需要将所有数据文件添加到内存,这就很耗内存
如果所有的查询都是等值查询,那么hash确实快,但实际上范围查找数据更多
智能处理键值得全值匹配
查询Hash函数决定着索引键的大小
要使InnoDB或MyISAM支持哈希索引,可以通过伪哈希索引来实现,叫自适应哈希索引。
可通过增加一个字段,存储hash值,将hash值建立索引,在插入和更新的时候,建立触发器,自动添加计算后的hash到表里。
哈希表这种结构适用于只有等值查询的场景,比如Memcached。
3 案例应用
假如有一个非常非常大的表,比如用户登录时需要通过email检索出用户,如果直接在email列建索引,除了索引区间匹配,还要进行字符串匹配比对,email短还好,如果长的话这个查询代价就比较大。 若此时,在email建立哈希索引,查询以int查询,性能就比字符串比对查询快多了。
Hash 算法
建立哈希索引,首先就要选定哈希算法,《高性能MySQL》说到的CRC32算法。
INSERT UPDATE SELECT 操作
在表中添加hash值的字段:
ALTER TABLE `User` ADD COLUMN email_hash int unsigned NOT NULL DEFAULT 0;
接下来就是在UPDATE和INSERT时,自动更新 email_hash 字段,通过触发器实现:
DELIMITER |
CREATE TRIGGER user_hash_insert BEFORE INSERT ON `User` FOR EACH ROW BEGIN
SET NEW.email_hash=crc32(NEW.email);
END;
|
CREATE TRIGGER user_hash_update BEFORE UPDATE ON `User` FOR EACH ROW BEGIN
SET NEW.email_hash=crc32(NEW.email);
END;
|
DELIMITER ;
这样SELECT请求就会变成:
SELECT `email`, `email_hash` FROM `User` WHERE
email_hash = CRC32(“xxoo@gmail.com”)
AND `email`= “xxoo@gmail.com”;
+----------------------------+------------+
| email | email_hash |
+----------------------------+------------+
| xxoo@gmail.com | 2765311122 |
+----------------------------+------------+
AND email = "xxoo@gmail.com" 是为了防止哈希碰撞时数据不准确。
来源:https://blog.csdn.net/weixin_60707895/article/details/121014425
猜你喜欢
- python数组和矩阵先创建一个一维数组直接定义一个数组:a = [1,2,3,4,5]b = ['a','c
- SUBSTR函数是用来截取数据库某一列字段中的一部分。 在各个数据库的函数名称不一样(真是蛋疼,后发明的数据库难道不能同先发明的一样吗?)
- 一、reversereverse()是python中列表的一个内置方法(在字典、字符串和元组中没有这个内置方法),用于列表中数据的反转例子:
- 今天一个同事报告一个问题,表都不能使用了,检查了一下,发现问题 db2 => select * from testACTNO ACTK
- Python用Pillow(PIL)进行简单的图像操作方法颜色与RGBA值计算机通常将图像表示为RGB值,或者再加上alpha值(通透度,透
- 如下所示:import sysfrom PyQt5.QtWidgets import QMainWindow, QTextEdit, QAc
- 大家好,今天给大家分享一下明哥整理的一篇 Python 参数的内容,内容非常的干,全文通过案例的形式来理解知识点,自认为比网上 80% 的文
- 图像有时候比数据更能满足人们的视觉需求Pytorch中保存图片的方式pytorch下保存图像有很多种方法,但是这些基本上都是基于图像处理的,
- 本文实例讲述了Python HTML解析模块HTMLParser用法。分享给大家供大家参考,具体如下:简介先简略介绍一下。实际上,HTMLP
- 大家好,我叫斑马纹列表中使用两种相同的样式但颜色不同的背景,来间隔显示的内容。当然这个释义我是借鉴《designing interfaces
- 文件数据读写读写文件,本质上是请求操作系统打开一个文件对象,然后,通过操作系统提供的接口从这个文件对象中读取数据(读文件),或者把数据写入这
- 线性回归在整个财务中广泛应用于众多应用程序中。在之前的教程中,我们使用普通最小二乘法(OLS)计算了公司的beta与相对索引的比较。现在,我
- 本文实例讲述了Python基于回溯法子集树模板解决0-1背包问题。分享给大家供大家参考,具体如下:问题给定N个物品和一个背包。物品i的重量是
- 环境python版本号系统游览器python 3.7.2win7google chrome关于本文本文将会通过爬虫的方式实现简单的百度翻译。
- Beautiful Soup就是Python的一个HTML或XML的解析库,可以用它来方便地从网页中提取数据。它有如下三个特点:Beauti
- key_len的含义在MySQL中,可以通过explain查看SQL语句所走的路径,如下所示:mysql> create table
- 1.C++ 代码Demo.h#pragma oncevoid GeneratorGaussKernel(int ksize, float s
- asp 中处理文件上传以及删除时常用的自定义函数:删除文件,建立目录的程序,根据原文件名生成新的随机文件名,CMS替换函数,将所有开始,结束
- 如果你从未为MySQL设置根用户密码,服务器在以根用户身份进行连接时不需要密码。但是,建议你为每个账户设置密码。如果你以前设置了根用户密码,
- Java一直标榜一句老话叫“编写一次,到处运行(Write Once,Run Anywhere)”,CSS也差一点点做到了。但就是为了差的一