我正在处理音频指纹问题,在这个问题上,我需要用行数(至少15亿行)来查询一个非常大的表,但在大小上(23G)相对比较好,并使用多个查询(在20到50个查询之间)检索大约50K到100 K的行。
该表有3列、一个散列和两个int值。没有任何限制。哈希列有许多冲突/重复项。以下是显示create表的输出
CREATE TABLE `fingerprints` (
`hash` binary(10) NOT NULL,
`int1` mediumint(8) unsigned NOT NULL,
`int2` mediumint(8) unsigned NOT NULL,
KEY `hash` (`hash`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci查询很简单,下面是一个示例:
select int1 ,int2 from fingerprints
WHERE hash in
(UNHEX("1ff99335cce004f2765d"),UNHEX("14c4b93ed575982ed2e4")
,UNHEX("41044b0cf21dc8ac8f9b"),UNHEX("a791403ca116b4da53dd")
,UNHEX("d9f91514b900c25fa095"),UNHEX("3349f906deae6cd32883")
,UNHEX("221c0e3e2bc243fb0fe5") .... more here);我尝试过不同的硬件规范(只使用一台机器/实例的AWS )。不同的my.cnf配置,但没有显著的性能提升。
此操作的目标速度阈值(总查询时间)为5秒。但是,我得到的最好结果是,一个查询的平均时间是3秒(如果我有20个查询,总的操作时间是1分钟)。
最后注意:在分析查询时,显示概要文件命令显示最慢的部分是(发送数据)状态。当结果集较大时,查询变得更慢(即检索10k行需要大约6秒,而检索1000行则需要2秒)。
问题:
我的设置:
显示索引输出:
+--------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
+--------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| fingerprints | 1 | hash | 1 | hash | A | NULL | NULL | NULL | | BTREE | | | YES | NULL |
+--------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+解释查询输出(对于示例查询)
+----+-------------+--------------+------------+-------+---------------+------+---------+------+------+----------+-----------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+--------------+------------+-------+---------------+------+---------+------+------+----------+-----------------------+
| 1 | SIMPLE | fingerprints | NULL | range | hash | hash | 10 | NULL | 4912 | 100.00 | Using index condition |
+----+-------------+--------------+------------+-------+---------------+------+---------+------+------+----------+-----------------------+发布于 2019-04-22 07:12:50
通过执行以下查询,我能够解决这个缓慢问题:
alter table fingerprints order by hash;这项工作大约需要60秒,现在只需要350毫秒。
发布于 2019-04-21 19:23:07
(UNHEXing并不是问题的重要部分。)
真正的问题是散列的随机性。这导致在磁盘上的许多地方跳跃。让我们剖析一下查询。
IN列表是分散在整个INDEX(hash)中的值列表。.MYI文件中找到)来查找的,该文件缓存在MyISAM的key_buffer中。key_buffer_size的价值是什么?SHOW TABLE STATUS LIKE 'fingerprints'的结果是什么?fingerprints.MYD。(记录的FIXED长度似乎是17个字节。)该怎么办呢?
案例1: Data_length + Index_length < RAM大小: key_buffer_size略大于Index_length。渐渐地,两个缓存将填充索引和数据,I/O将消失。
案例2:这个总数略大于RAM:选择一个缓存就足够大了。
案例3:和要比RAM大得多:在得到更多RAM之前,您会被大量的I/O所困。
我怀疑Data_length和Index_length差不多。我会将可用内存分成一半-一半用于key_buffer_size,其余用于数据缓存。
以下是两个更多的想法:
KEY(hash, int1, int2),这意味着只需要BTree查找;数据将位于叶节点中。使用这种方法,您可以将key_buffer_size设置为“大部分”可用内存。SELECT不会触及数据,只会触及索引。key_buffer_size缩小到20M,并将innodb_buffer_pool_size提高到内存的70%。其他说明:
发布于 2019-04-10 00:05:37
当查询包括,
(“1ff99335cce004f2765d”),UNHEX(“14.
将永远局限于缓慢。每一行都必须“取消十六进制”才能确定此查询的相关性。在您的示例中,每行检索几个UNHEX操作。
https://dba.stackexchange.com/questions/234081
复制相似问题