我正试图找出从具有类似以下结构的数据库中提取值的最有效方法:
表格测试:
int id (primary, auto increment)
varchar(50) stuff,
varchar(50) important_stuff;
我需要做一个查询,比如
select * from test where important_stuff like 'prefix%';
整个表的大小大约是1000万行,但是对于重要的东西只有大约500到1000个不同的值。我目前的解决方案是索引
important_stuff
但是性能并不令人满意。最好创建一个单独的表,将distinctimportant_stuff
与某个id匹配,并将其存储在“test”表中,然后(select id from stuff_lookup where important_stuff like 'prefix%') a join select * from test b where b.stuff_id=a.id
或者这个:
select * from test where stuff_id exists in(select id from stuff_lookup where important_stuff like 'prefix%')
什么是优化这类事情的最佳方法?
最佳答案
innodb_buffer_pool_size
有多大?有多少内存可用?前者应该是后者的70%左右。你马上就会明白我为什么要提起这个设置。
根据你建议的3个选择,原来的一个和两个复杂的一样好。在另一些情况下,复杂的公式可能更有效。INDEX(important_stuff)
是
select * from test where important_stuff like 'prefix%';
现在,让我们研究一下该查询如何处理该索引:
进入BTree索引,从'prefix'开始。(努力:几乎是瞬间的)
向前扫描1000个条目。大约10个InnoDB块(每个16KB)。每个条目都有主键(
id
)。(努力:对于每个条目,查找行(这样您就可以得到“*”)这是BTree中包含PK和数据的1000个PK查找。最多也就10个街区。最坏的情况下,他们可能在1000个独立的街区。(努力:10-1000个街区)总工作量:约1010块(最坏情况)。
一个标准的旋转磁盘每秒可以处理大约100次读取。所以。我们看10秒。
现在,再次运行查询。猜猜怎么着;所有这些块现在都在RAM中(缓存在“buffer_pool”中,希望它足够大,可以容纳所有块)。不到一秒钟。
OPTIMIZE TABLE
没有必要!这不是一个统计数据刷新,而是缓存加速了查询。