我知道如果表太大,索引很难放入缓冲池,所以使用索引可能会导致大量的随机磁盘io。因此,一般来说,全表扫描可能比索引扫描快得多,即使它只读取大约%1行。
What I am confused about is :
[0] If there are a big table( 30 millions rows),and many small tables(each table can be fit into memory(buffer)),
will the big table also affect query about small tables ?
My logic is <======>
the buffer is shared by the whole database, so the big table will take most of buffer.
So the indexes of small tables can also hardly be fit into buffer(or it's often
removed from the buffer). Then the above conclusion(full table scan vs index scan) can be applied to this case .
[1] When the big table are partitioned into may small tables(in just one machine), the situation of buffer should keep identical.
So such partition cannot solve this problem(full table scan vs index scan), right? so the "big table" should not mean "one big table", but the "huge database or the sum of data is large"
总而言之,我的加入对吗?如果错了,为什么?请给我一个提示。非常感谢。
1条答案
按热度按时间rjee0c151#
这个
buffer_pool
在所有表、数据和索引中共享。但你所说的其余部分需要关注“块”而不是“表”。缓存是按块执行的。一个块(在innodb中)是16kb。大部分
innodb_buffer_pool_size
专用于数据和索引块。缓存作为lru(最近最少使用的)运行(大约)——也就是说,最近最少使用的块在需要其他块时从缓存中抛出。
不,表或索引没有“完全”加载到缓存中。相反,在需要时加载(和清除)所需的块。
如果所有的数据和索引都适合缓存,那么(最终)所有的块都将“生存”在那里。
如果数据加索引太大,那么块将根据需要来来去去。通常情况下,这几乎和把它们都装上一样好。例如,如果您通常使用“最近”的记录,那么包含它们的块将“停留”在缓存中;与此同时,“老”街区将被冲出。
如果您使用的是uuid(guid),那么性能可能会变得非常糟糕——这是因为这样的索引值具有随机性。
无论缓存中的内容是否太大,都应该避免全表扫描(和全索引扫描)。它们代价高昂,通常可以通过适当的索引和/或查询公式来避免。
当你在一个比缓存大的表上做一个完整的表扫描时,一定会有什么结果。您将不得不执行一些i/o操作,一些块将从缓存中跳出。但是,有一种内置的技术可以防止为了偶尔的表扫描而盲目地清除整个缓存。为了进一步讨论,研究
innodb_old_blocks_pct
. (不,我不建议将其从默认值更改为37%。)划分表是什么意思?如果你指的是内置的
PARTITION
机制,那又怎样?如果你扫描一个表,你就是在扫描所有的分区。相同数量的块;对缓存的影响相同。我已经处理了超过缓冲池10倍或更多的表集。我可以讨论性能技巧,但我需要一个具体的
SHOW CREATE TABLE
(带或不带)PARTITIONs
)以及一些顽皮的查询(例如表扫描)。优化器在执行表扫描和使用基于各种统计信息的索引等之间进行选择。经验法则是,如果需要触及超过20%的行,它将执行表扫描,而不是在索引和数据之间跳转(注意:截止值比你提到的1%要高得多。)
索引的结构是
BTree
在16kb的数据块中,所以从中间开始扫描一个范围是非常有效的。例如:INDEX(last_name)
为了WHERE last_name LIKE 'J%'
可能会对索引的10%进行“范围扫描”,即使这涉及到大量跳转到表中。