【问题标题】:Method to not parse the whole table for an SQL Query in Java - JDBC不为 Java 中的 SQL 查询解析整个表的方法 - JDBC
【发布时间】:2019-12-20 18:28:44
【问题描述】:

假设我们有一个非常大表,并且我们有以下形式的查询(这只是一个示例)

SELECT personID FROM people WHERE birthYear>2010 LIMIT 50

我想最大化获取该查询结果的性能,问题是数据库将解析整个表以找到匹配条件的元组,然后返回前 50 个。如果我们有,那就是一个问题具有数百万或数十亿元组的数据库。

在 Java - JDBC 或 SQL 中有没有办法不解析整个表,而是逐步解析它并获取前 50 个匹配条件的行,或者解析前 1000 行并获取所有匹配的行,并在用户单击“显示更多”按钮时继续获取更多结果?

感谢您的宝贵时间。

【问题讨论】:

  • 您在birthYear 列上有索引吗?您限制 50 条记录,但按什么顺序?你总是需要一个带有 LIMIT 的 order by 子句,否则 mysql 会随机返回 50 条记录
  • 查询只是一个例子。它不会总是 WHEREbirthYear 等。

标签: java mysql sql jdbc query-optimization


【解决方案1】:

问题不是真的。以下是对可能发生的情况的分析:

SELECT personID FROM people WHERE birthYear>1900 LIMIT 50
SELECT personID FROM people WHERE birthYear>2010 LIMIT 50

案例1:birthYear没有索引:

  • 1900:它只会扫描表直到 50 行匹配WHERE 子句。这可能是前 50 个。
  • 2010:它将扫描大部分或全部表格,除非它是幼儿目录。因此,它可能需要读取所有行才能找到 50。

案例2:索引birthYear:

开头

它会跳到索引的中间到第一个大于 1900(或 >2010)的值,然后抓取接下来的 50 行(或更少)。对于这些行中的每一行,它将到达personID 的表中。

案例3:INDEX(birthYear, personID)

与案例 2 一样,但不需要“伸手可及”。这是因为personID 是索引的一部分。

仅在情况 1 中,并且仅当少于 50 行的行数 >1900(似乎不太可能)时,它才会扫描整个表。案例 2 和 3 在 50 时立即停止。

【讨论】:

  • 是真的吗?当我这样做时,查询结果的大小是总行数,这就是为什么我认为它会扫描整个表。没有?
  • @PavTze - 你有 1900 年以前出生的人吗?我认为没有人活得那么老。
  • 换一种说法,... 优化器使用任何可用的方法来最小化要执行的工作——索引、WHERE、LIMIT 等。
  • 查询是一个例子,它可以是任何需要的值,而不是 1900。所以我关于案例 1 的问题是对于任何具有 LIMIT 的查询,它是否会解析表直到 50行是否匹配 where 子句?
  • @PavTze - 如果允许最终用户创建查询,则将进行表扫描;试图阻止这种情况非常复杂。另一方面,如果您提供 API,您可以控制用户提出的“问题”,那么您可以(大部分)防止“慢”查询。但这意味着当用户需要新功能时愿意加入并添加索引。并且仍然会有难以优化的查询。 (看看这个论坛上所有要求“优化”或“更快”或“性能”的查询。)
【解决方案2】:

在这种情况下你必须做两件事-

  1. 创建birthYear 和personID 的索引
  2. 按年对表进行分区

【讨论】:

    猜你喜欢
    • 2015-01-07
    • 1970-01-01
    • 1970-01-01
    • 2015-07-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-06
    • 1970-01-01
    相关资源
    最近更新 更多