为字符串类型构建MySQL自己的hash索引

本文介绍了一种利用CRC32校验和替代字符串匹配的方法,以减少MySQL中字符串比较带来的性能开销。通过对user_nick字段计算CRC32值并建立索引,实现了快速查找,显著提高了查询效率。

这是一个真实的场景,表的定义如下:

CREATE TABLE `user` (
`id` bigint(20) NOT NULL,
`user_nick` varchar(32),
`user_source` tinyint(4) NOT NULL ,
`user_type` tinyint(4) NOT NULL,
........
`version` int(11) DEFAULT '0' COMMENT '版本',
`crc_user_nick` bigint(20) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `idx_user_nick` (`user_nick`),
KEY `idx_crc_user_nick` (`crc_user_nick`)
) ENGINE=InnoDB DEFAULT CHARSET=gbk;

为了显示对比结果,我为user_nick列添加了一个索引,同时添加了一个存放crc32的字段crc_user_nick列,同时在这列上创建了一个索引,

update user set crc_user_nick=crc32(user_nick);

表中有将近200w的数据,并且user_nick不允许重复,随机抽取一条查询,根据crc查询:

root@test 01:25:34>set profiling=1;
Query OK, 0 rows affected (0.00 sec)

root@test 01:25:37>select * from user where crc_user_nick=3741129210;

耗时:1 row in set (0.40 sec)

root@test 01:25:42>show profile cpu,block io for query 1;
+--------------------------------+----------+----------+------------+--------------+---------------+
| Status | Duration | CPU_user | CPU_system | Block_ops_in | Block_ops_out |
+--------------------------------+----------+----------+------------+--------------+---------------+
| starting | 0.000042 | 0.000000 | 0.000000 | 0 | 0 |
| checking query cache for query | 0.000089 | 0.001000 | 0.000000 | 0 | 0 |
| Opening tables | 0.388417 | 0.014998 | 0.004999 | 0 | 0 |
| System lock | 0.000013 | 0.000000 | 0.000000 | 0 | 0 |
| Table lock | 0.000012 | 0.000000 | 0.000000 | 0 | 0 |
| init | 0.000084 | 0.000000 | 0.000000 | 0 | 0 |
| optimizing | 0.000025 | 0.000000 | 0.000000 | 0 | 0 |
| statistics | 0.003755 | 0.000000 | 0.000000 | 0 | 0 |
| preparing | 0.000025 | 0.000000 | 0.000000 | 0 | 0 |
| executing | 0.000003 | 0.000000 | 0.000000 | 0 | 0 |
| Sending data | 0.001021 | 0.000000 | 0.000000 | 0 | 0 |
| end | 0.000004 | 0.000000 | 0.000000 | 0 | 0 |
| query end | 0.000004 | 0.000000 | 0.000000 | 0 | 0 |
| freeing items | 0.000043 | 0.000000 | 0.000000 | 0 | 0 |
| logging slow query | 0.000003 | 0.000000 | 0.000000 | 0 | 0 |
| cleaning up | 0.000004 | 0.000000 | 0.000000 | 0 | 0 |
+--------------------------------+----------+----------+------------+--------------+---------------+

对比同一条记录使用user_nick查询,

root@test 10:59:32>set profiling=1;
Query OK, 0 rows affected (0.00 sec)

root@test 10:59:41>select * from user_nick where user_nick='one001008104075924';

耗时:1 row in set (0.55 sec)

root@test 01:24:24>show profile cpu,block io for query 1;
+--------------------------------+----------+----------+------------+--------------+---------------+
| Status | Duration | CPU_user | CPU_system | Block_ops_in | Block_ops_out |
+--------------------------------+----------+----------+------------+--------------+---------------+
| starting | 0.000042 | 0.000000 | 0.000000 | 0 | 0 |
| checking query cache for query | 0.000089 | 0.000000 | 0.000000 | 0 | 0 |
| Opening tables | 0.542834 | 0.011998 | 0.003000 | 0 | 0 |
| System lock | 0.000013 | 0.000000 | 0.000000 | 0 | 0 |
| Table lock | 0.000011 | 0.000000 | 0.000000 | 0 | 0 |
| init | 0.000090 | 0.000000 | 0.000000 | 0 | 0 |
| optimizing | 0.000028 | 0.000000 | 0.000000 | 0 | 0 |
| statistics | 0.000315 | 0.000000 | 0.000000 | 0 | 0 |
| preparing | 0.000025 | 0.000000 | 0.000000 | 0 | 0 |
| executing | 0.000003 | 0.000000 | 0.000000 | 0 | 0 |
| Sending data | 0.007554 | 0.000000 | 0.000000 | 0 | 0 |
| end | 0.000004 | 0.000000 | 0.000000 | 0 | 0 |
| query end | 0.000004 | 0.000000 | 0.000000 | 0 | 0 |
| freeing items | 0.000043 | 0.000000 | 0.000000 | 0 | 0 |
| logging slow query | 0.000002 | 0.000000 | 0.000000 | 0 | 0 |
| cleaning up | 0.000004 | 0.000000 | 0.000000 | 0 | 0 |
+--------------------------------+----------+----------+------------+--------------+---------------+

通过profile我们可以明显的看到使用user_nick的时候,耗时主要用在opening tablesSending data,在一些字符类型过滤较高的条件上,我们可以采用这种方法来优化查询。

参考:《High Performance MySQL》




转载于:https://www.cnblogs.com/sunss/archive/2012/01/17/2323644.html

### MySQL 索引类型及其用途 #### B-Tree 索引 B-Tree 索引是最常见的索引类型之一,在大多数情况下都能提供良好的性能。这种索引适用于范围查询、精确匹配以及排序操作。对于 `=`、`>`、`<`、`>=`、`<=`、`BETWEEN` 和 `IN` 这样的比较运算符,B-Tree 索引能够有效地加速这些条件下的数据检索过程[^1]。 ```sql CREATE INDEX idx_btree ON table_name (column_name); ``` #### 哈希索引 哈希索引专门用于处理相等性的查找,即当 SQL 查询中仅涉及 `=` 操作时表现最佳。由于哈希函数的特点决定了它不适合范围查询或者部分匹配的操作,因此应用场合相对有限。此外,哈希索引不支持有序扫描,这意味着即使表中有顺序排列的数据也无法利用这一点来优化读取效率[^3]。 ```sql CREATE HASH INDEX idx_hash ON table_name (column_name); ``` #### 全文索引 为了满足自然语言文本搜索的需求而设计的一种特殊形式的索引——全文索引应运而生。通过创建 FULLTEXT 类型索引可以在较大的字符串字段上实现高效的关键词定位功能,尤其适合于文章内容、评论区留言之类的大段文字资料管理场景下使用。 ```sql ALTER TABLE articles ADD FULLTEXT(title,body); ``` #### 空间索引 针对地理信息系统(GIS)中的坐标点集合作为空间对象建立起来的空间索引,则主要用于解决地理位置相关的复杂计算问题,比如两点之间的距离测量或是多边形区域内的位置判断等任务。这类索引通常基于 R-tree 结构构建而成。 ```sql CREATE SPATIAL INDEX sp_index ON geom_table(gis_column); ``` #### 聚簇索引与非聚簇索引 这两种概念主要区别在于它们如何组织实际存储记录的位置关系。在一个拥有聚簇索引的表格里,所有的行都会按照该索引键值被物理地存放在磁盘上的连续区域内;而非聚簇索引则是另外一种结构化方式,其中包含了指向对应真实数据所在地址的信息条目而不是直接存放整行的内容副本。 #### 前缀索引 如果某个列包含非常长的字符序列作为其值的话,那么就可以考虑为其设置前缀长度并据此生成相应的索引来代替整个字段参与索引机制之中。这样既节省了空间又提高了访问速度,不过需要注意的是过短的前缀可能会降低区分度从而影响到最终的效果。 ```sql CREATE INDEX part_of_name ON customer (name(10)); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值