Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/57.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
mysql范围查询性能_Mysql_Performance_Indexing_Range - Fatal编程技术网

mysql范围查询性能

mysql范围查询性能,mysql,performance,indexing,range,Mysql,Performance,Indexing,Range,我有一个简单的MySQL表,有40000行: id CHAR(36) (i am using UUIDs as primary keys) number_from (INT) number_to (INT) 有3个索引: primary(id) number_from(number_from) number_to(number_to) 看起来像下面这样的简单查询需要相当大的时间 时间量,如30秒或更长: SELECT * FROM numbers WHERE (number_from >

我有一个简单的MySQL表,有40000行:

id CHAR(36) (i am using UUIDs as primary keys)
number_from (INT)
number_to (INT)
有3个索引:

primary(id)
number_from(number_from)
number_to(number_to)
看起来像下面这样的简单查询需要相当大的时间 时间量,如30秒或更长:

SELECT * FROM numbers WHERE (number_from >= 703911711 AND number_to <= 703911800)

我能做些什么来优化性能呢?

分离索引将迫使MySQL单独扫描它们。如果将number_from和number_to索引在一起,MySQL可以在单个索引上执行整个where子句:

CREATE INDEX number_from_number_to_ind
ON numbers (number_from, number_to)
将id添加到索引实际上将允许MySQL执行整个查询,而无需访问表,但代价是使索引大大增大。您必须进行基准测试,看看这是否真的提高了查询的性能:

CREATE INDEX all_columns_ind
ON numbers (number_from, number_to, id)

你有两个问题不容易解决

UUID是非常“随机”的, 优化器不理解从到的范围不重叠 但首先,让我们确保缓存设置正确。如果您使用的是MyISAM,则键缓冲区大小应为可用RAM的20%左右。或者对于InnoDB,InnoDB的缓冲池大小应该是可用RAM的70%左右。如果您有小的设置,这个更改只会将问题从I/O转移到CPU。当您无法在RAM中缓存大多数表及其索引时,它将无法扩展

解释了为什么uuid对于大型索引很糟糕。它还提供了一个存储函数,以使UUID更小,从而更易于缓存;这将有助于I/O

如果您有类型1的UUID,比如MySQL生成的UUID,那么博客还解释了为什么在函数的帮助下,UUID的使用可以扩展。但如果它是UUID的其他类型,并且必须至少有一个包含UUID的BTree索引或主键,那么您的任务是不可伸缩的。你能把它变成自动增量吗?这将允许插入在表的“末端”聚集,而不是随机分散在表中,从而破坏缓存


至于范围,您需要修改该表,以便在每行中只放置一个from/to。这涉及到“无主”范围的额外行。然后编写一个存储的例程来使用limit1来防止您看到的情况,即无法有效地使用任何索引。详细介绍了IPv4和IPv6的架构设计和参考代码。我的代码具有很强的可伸缩性,消除了您提出的索引问题。

当范围的边界存储在不同的属性中时,传统的索引不起作用。正如许多人发现并记录的那样,解决方案是使用地理空间索引。这是谷歌的第一次成功


由于mysql地理空间索引可以在二维中工作,所以诀窍是将范围映射到一个维度,并在另一个维度中使用固定比例。

请发布EXPLAIN SELECT*from…..的输出。。。。。即使没有使用索引,仅40k行上的30秒似乎也太多了。同时发布SHOW CREATE TABLE numbers的输出,这样我们可以在上下文中看到完整的定义。不要选择*显式定义字段名而不是标题。我认为不需要最后一个索引,至少innodb不需要。主键隐式出现在每个次要索引中。我的灵感来自于你的答案和链接的博客文章,所以我尝试将其应用于datetime列。然而,我面临着这个问题