- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章MySQL字符串索引更合理的创建规则讨论由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
前言 。
针对使用MySQL的索引,我们之前介绍过索引的最左前缀规则,索引覆盖,唯一索引和普通索引的使用以及优化器选择索引等概念,今天我们讨论下如何更合理的给字符串创建索引.
如何更好的创建字符串索引 。
我们知道,MySQL中,数据和索引都是在一颗 B+树 上,我们建立索引的时候,这棵树所占用的空间越小,检索速度就会越快,而varchar格式的字符串有些会很长,那么在效率为上的今天,我们如何更加合理的建立字符串的索引呢? 假如说我们一张表中存在 email 字段,现在要给 email 字段创建索引,email 字段值的格式为:zhangsan@qq.com.
有2种建立索引的方式:
1、直接给 email 字段建立索引:alter table t add index index1(email),
索引树结构为:
2、建立 email 的前缀索引:alter table t add index index2(email(6)),
索引数据结构为:
此时我们的查询语句为:select id,name,email from t where email='zhangsh123@xxx.com',
当使用index1索引时其执行步骤为:
1、从index1索引树查找索引值为zhangsh123@xxx.com的主键值ID1; 。
2、根据ID1回表查到该行数据确实为zhangsh123@xxx.com,将结果加入结果集; 。
3、继续查找index1索引树下一个索引值是否满足zhangsh123@xxx.com,不满足则结束查询.
当使用index2索引时其执行步骤为:
1、从index2索引树查找索引值为zhangs的主键值ID1; 。
2、根据ID1回表查到该行数据确实为zhangsh123@xxx.com,将结果加入结果集; 。
3、 继续查找index2索引树下一个索引值是否满足zhangs,满足则继续回表查询该行数据是否为zhangsh123@xxx.com,不是则跳过继续查找; 。
4、持续查找index2索引树,直到索引值不是zhangs为止.
从以上分析中我们可以看出,全字段索引相比前缀索引来说,减少了回表的次数,但是如果我们将前缀从6个增加到7个8个的话,前缀索引回表的次数就会减少,也就是说,只要定义好前缀的长度,我们就能既节省空间又保证效率.
那么问题来了,我们怎么衡量使用前缀索引的长度呢?
1、使用 select count(distinct email) as L from t; 查询字段不同值的个数; 。
2、依次选取不同的前缀长度查看不同值的个数:
1
2
3
4
5
6
|
select
count
(
distinct
left
(email,4))
as
L4,
count
(
distinct
left
(email,5))
as
L5,
count
(
distinct
left
(email,6))
as
L6,
count
(
distinct
left
(email,7))
as
L7,
from
t;
|
然后根据实际可接受的损失比例,选取适合的最短的前缀长度.
前缀的长度问题我们解决了,但是一个问题是,如果使用前缀索引,那我们索引覆盖的特性就用不到了。 用全字段索引时,当我们查询select id,email from t where email='zhangsh123@xxx.com';时,不用回表直接就能查到id和email字段.
但是用前缀索引时,MySQL并不清楚前缀是否会整个覆盖email的值,无论是否全包含都会根据主键值回表查询判断.
所以说,使用前缀索引虽然能节省空间保证效率但是却不能用到覆盖索引的特性,是否使用就在于具体考虑了.
其他字符串索引创建方式 。
实际情况实际考虑,并不是所有的字符串都能使用前缀截取的方式创建索引,如身份证号或者ip这些字符串使用前缀索引就不合理了,身份证号一般同一个地区的人前几位都是一模一样的,使用前缀索引就不合理了,而ip值我们一般在实际中将其转化为数字去存储.
针对身份证号,我们可以使用倒叙存储,取前缀创建索引或者使用crc32()函数来获取一个hash校验码(int值)当做索引.
倒叙:select field_list from t where id_card = reverse('input_id_card_string'),
crc32:select field_list from t where id_card_crc=crc32('input_id_card_string') and id_card='input_id_card_string' 。
这两种方式相对来说效率都差不多,都不支持范围查找,支持等值查找.
在倒叙方式中,需要使用reverse函数,但是回表次数可能比hash方式多.
在hash方式中,需要新建一个索引字段并调用crc32()函数。(注意:crc32()函数获取的结果不保证能唯一,可能存在重复的情况,但是这种情况概率较小),回表次数少,几乎1次就行.
最后 。
针对字符串索引,一般有以下几种创建方式:
1、字符串较短,直接全字段索引 。
2、字符串较长,且前缀区分度较好,创建前缀索引 。
3、字符串较长,前缀区分度不好,倒叙或hash方式创建索引(这种方式范围查询就不行了) 。
4、根据实际情况,遇到特殊字符串,特殊对待,如ip.
总结 。
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对我的支持.
原文链接:https://segmentfault.com/a/1190000021086051 。
最后此篇关于MySQL字符串索引更合理的创建规则讨论的文章就讲到这里了,如果你想了解更多关于MySQL字符串索引更合理的创建规则讨论的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
问题:您好,我已经为我的一个客户创建了一个 DBMS,其中有一个功能,即从相同的表单输入将值拆分为四个不同的表(但是)有时会发生值输入到 table1 和 table2 而不是 table3 和 ta
我正在开发基于 Web 的应用程序,该应用程序需要在将任何文件上传到服务器之前检查其大小。 如果 Web 开发人员可以通过任何方式在客户端检查文件大小而不是在服务器端检查文件大小,从而避免不必要的服务
Closed. This question is opinion-based。它当前不接受答案。 想改善这个问题吗?更新问题,以便editing this post用事实和引用来回答。 5年前关闭。
好的,这个线程将更像是对标题中提到的主题的讨论。我一遍又一遍地搜索整个主题,但没有找到适合我的好/可接受的解决方案。 场景 假设我有一个 android 项目,我需要一个第三方库(例如 drag-so
我正在进行的项目使用用户创建的多个“墙”进行讨论。 我的问题涉及如何在 MySQL 数据库中对此进行建模。 拥有一个名为“walls”的表,其中包含诸如创建者等信息,以及另一个名为“messages”
按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit th
发现了一个有趣的问题,我首先在 WinForms 中发现,然后在 Silverlight 中再次发现,而且在数据绑定(bind)方面也很可能是 WPF。 我有一个带有多个选项卡的选项卡控件。当用户点击
我正在用 VBA 编写一个方法,但我收到了 ByRef 参数类型不匹配。在做了一些研究之后,我找到了一个快速的解决方法——将我的值存储在另一个变量中,然后将该新变量传递给我的方法。谁能向我解释疯狂背后
关闭。这个问题是opinion-based 。目前不接受答案。 想要改进这个问题吗?更新问题,以便 editing this post 可以用事实和引文来回答它。 . 已关闭 7 年前。 Improv
我一直在尝试修改 Odoo 讨论,但没有成功。 这就是我要实现的目标: 我将带有“新消息”按钮的消息添加到 Odoo 模块(在类 mro.order 中)。消息显示在讨论模块中: 但我需要标题类似于“
关闭。这个问题是off-topic .它目前不接受答案。 想改进这个问题吗? Update the question所以它是on-topic用于堆栈溢出。 关闭 9 年前。 Improve this
为任何错误的术语道歉——我对计算机科学很陌生,我几乎只知道 Clojure(但我想我会说我很了解它)。 所以,我没有对此进行大量研究,但有时我发现在编写 Clojure 代码时它很有用,以便能够从该数
a) 匿名卷 使用数据容器时,您可以像这样使用匿名卷 version '2' services: consumer: volume_from: - data-container
var yourObjects = [ { object: {obj1:"aa"}, direction: 'top' }, { object: "obj2", direction: 'left' }
我正在尝试使用 Disqus API 将帖子添加到现有的讨论/论坛。在文档中我可以读到我可以作为访客发送评论而无需身份验证。文档是这样说的: http://disqus.com/api/docs/po
因此,我偶然发现了一本名为“C++科学计算指南”的C++书的练习。 这是练习: “编写代码,为三个2×2矩阵的 double 浮点数A,B,C动态分配内存,并为A和B的条目分配值。令C = A +B。
规则 CA1008指定所有枚举都应具有 0 值,该值应命名为 Unknown(我们不在此处讨论标志)。我理解您想防止未初始化的值自动获得意义的原因。假设我定义了以下枚举: enum Gender {
前几天,Google 通知我,我的 Gmail 帐户可能已被盗用,因为它已被两个来自异常位置的 IP 地址访问。由于我通常(并且愚蠢地)为每个网站使用相同的密码,所以我决定改变一下并使用不同的密码。
RubyGems.org ,官方 gems 站点,提供的功能很差。我想为我的网站找到一些好的 gems,但这是不可能的——它只提供了几个“新 Gems”/“今天下载最多的” gems,以及所有的列表
我如何提取我博客中的最新对话(整个网站)并显示最近的 10 条评论作为来自 Disqus 的对话摘要? 最佳答案 您可以使用 Disqus 论坛/listPosts API 方法构建一个最新评论小部件
我是一名优秀的程序员,十分优秀!