【问题标题】:Fetch rows with primary keys within range获取范围内主键的行
【发布时间】:2013-08-25 23:42:09
【问题描述】:

是否有可能在重负载下有效地对大表(可能是十亿行)进行范围扫描,以获取范围内主键的所有行。主键是BIGINT 类型。除了主键之外,行非常短,只是另一个 INT 字段。仅对该表执行这种类型的查询。

反正要优化这样的查询,还是表?可能我可以存储始终排序的行,以便范围扫描更容易?

是否有可能在大表上以良好的性能进行此类查询?

【问题讨论】:

    标签: mysql sql optimization database-design query-optimization


    【解决方案1】:

    主键列会自动编制索引,因此对范围的访问应该会执行得非常好。使用BETWEEN 条件:

    select * from mytable
    where id between ? and ?
    

    当然,如果范围很大,由于返回的行数很大,性能会很慢。

    此外,如果范围的大小超出某个限制(优化器会决定,但通常是总行数的 1/11),则不会使用索引,而是会进行完整的故事扫描,因为它实际上是如果被访问的行的百分比足够大,则比使用索引更快。

    如有疑问,请在查询上运行EXPLAIN 以显示访问是如何完成的。如果它使用索引,它可能会尽可能快。

    【讨论】:

    • 不,我也不想获取整个范围,我会限制它最多 1000 行(这是最大和罕见的)& 范围永远不会覆盖所有行的 1/1000。可以对行进行排序吗?这对性能有帮助吗?
    • 不排序。只需在我的回答中使用查询即可。
    • 谢谢。我认为我的陈述有点模棱两可,我的意思是在表中存储按主键顺序排序的行,这样对于 MySQL 来说范围扫描非常容易。
    • 顺便说一句,还要澄清这些BIGINTs(它们是主键)实际上是由两个4字节INTs组成的。我需要在我的应用程序中存储用户的主题列表(最多 500 个)。所以有两种方法,要么我只是合成 (userId+topicId) 并将结果BIGINT 存储为主键并使用上面解释的范围扫描,否则有些人也这样做,为 userId 和 topicId 使用两个单独的字段& 做类似select * from mytable where userid=? 的查询。但是第二种方法不会在表中创建任何主键,所以我不确定它是否提供相同或更好的性能?!
    猜你喜欢
    • 2011-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-22
    • 1970-01-01
    • 2021-06-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多