【问题标题】:In mysql(innodb),how does the big table affect buffer(memory)?在mysql(innodb)中,大表如何影响缓冲区(内存)?
【发布时间】:2018-06-13 07:37:22
【问题描述】:

我知道如果一个表太大,索引就很难放入buffer_pool, 所以使用索引可能会导致大量的随机磁盘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"

总而言之,我的加入对吗?如果错了,为什么?请给我一个提示。非常感谢。

【问题讨论】:

    标签: mysql database caching innodb


    【解决方案1】:

    buffer_pool 在所有表、数据和索引之间共享。但是你所说的其余部分需要关注“块”而不是“表”。

    缓存以为基础执行。一个块(在 InnoDB 中)是 16KB。大多数innodb_buffer_pool_size 专用于数据和索引块。

    缓存运行(大约)为 LRU(最近最少使用)——也就是说,当需要其他块时,从缓存中丢弃最近最少使用的块。

    不,表或索引没有“完全”加载到缓存中。而是在需要时加载(并清除)所需的块。

    如果所有数据 索引都适合缓存,那么(最终)所有块都将“存在”在那里。

    如果数据加索引太大,那么块会根据需要来来去去。 通常这几乎与将它们全部加载一样好。例如,如果您通常使用“最近”记录,那么包含它们的块将“保留”在缓存中;同时“旧”块将被撞出。

    如果您使用 UUID (GUID),性能会变得非常糟糕——这是因为此类索引值的随机性。

    全表扫描(和全索引扫描)无论是否太大而无法放入缓存,都应避免。它们成本高昂,通常可以通过适当的索引和/或查询公式来避免。

    当您对比缓存大的表执行全表扫描时,必须付出一些努力。您将不得不做一些 I/O,并且一些块将被撞出缓存。但是,有一种内置技术可以防止盲目地清除整个缓存以进行偶尔的表扫描。如需进一步讨论,请研究innodb_old_blocks_pct。 (不,我不建议将其从默认的 37% 更改。)

    对表进行分区是什么意思?如果您的意思是内置的PARTITION 机制,那又如何?如果您扫描一个,您正在扫描所有个分区。相同数量的块;对缓存的影响相同。

    我已经处理了超过 buffer_pool 10 倍或更多的表集。我可以讨论性能技术,但我需要一个特定的SHOW CREATE TABLE(有或没有PARTITIONs)和一些顽皮的查询(例如表扫描)。

    优化器在进行表扫描和使用基于各种统计数据等的索引之间进行选择。经验法则是,如果超过 20% 的行需要被触及,它将进行表扫描,而不是在索引和数据之间弹跳。 (注意:截止值远高于你提到的 1%。)

    索引的结构为BTree 16KB 块,因此从中间开始扫描范围非常有效。例如:INDEX(last_name) for WHERE last_name LIKE 'J%' 可能会对索引的 10% 进行“范围扫描”,即使这涉及到大量弹回表。

    【讨论】:

    • 谢谢你的回答,你说的我明白了,但我还是有一点困惑:如果整个数据库的块更大,那么访问一个表时必须做磁盘IO的概率(甚至如果它很小)可能会更高,对吧?因为它的块可能已经从缓存中删除了。那么当优化器选择索引扫描(除了索引转换)时,随机磁盘的次数可能会增加,对吧?可能选择全表扫描或索引扫描的阈值应该根据全库的块数来调整,对吧?
    • @pyb1993 - 一次磁盘命中的成本(时间)基本上是恒定的。 number 磁盘命中是我正在讨论的。由于索引和数据中记录的 order 与需要访问它们的 order 相比,您的概括性会崩溃——这些可能会导致非常少的 I/O与大量 I/O 相比。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多