【问题标题】:MySQL check large amount of dataMySQL检查大量数据
【发布时间】:2021-06-01 20:52:21
【问题描述】:

我有两个表名为 actualcheck

actual 包含 5000 万行,每行包含 32 位哈希

check 包含 1000 万行,每行包含 32 位哈希

我必须验证check 表中的哈希值是否在actual 表中。

我尝试了类似的 MySQL Join 查询

SELECT * 
  FROM `check` 
  LEFT 
  JOIN `actual` 
    on `check`.hash = `actual`.hash;

即使在 16GB RAM 机器上 MySQL 也会崩溃。

我尝试使用 PHP 脚本,将附加字段添加到表 check 作为字段名称哈希、状态、找到。

Status & found 默认为 0,PHP 将检查每条记录并将状态更新为 1,如果找到则更新为 1。

有什么方法可以更快地检查数百万或记录吗?

另一种方法是我使用 IGNORE 插入唯一的哈希并检查有多少没有附加,但它的过程很复杂。

我使用的 PHP 代码很慢

$sql = "SELECT * FROM `check` where status = 0 LIMIT 0, 1";
$result = $conn->query($sql);

if ($result->num_rows > 0) {
  while($row = $result->fetch_assoc()) {

    $check = "SELECT * FROM `actual` where hash = '".$row["hash"]."'";
    $checkx = $conn->query($check);

    $checky = "UPDATE `check` SET `status` = 1, `found` = 0 WHERE hash = '".$row["hash"]."'";
    $conn->query($checky);
    if ($checkx->num_rows > 0) {
      $checky = "UPDATE `check` SET `status` = 1, `found` = 1 WHERE hash = '".$row["hash"]."'";
      $conn->query($checky);
      }
    }
  }

【问题讨论】:

  • 列有索引吗?
  • @Raptor - 是的。
  • 我们可以看到两个表的 SHOW CREATE TABLE 语句,以及您查询的 EXPLAIN 吗?
  • 如果你是在php中执行select来使用检索到的数据来更新记录,那就不用麻烦了,直接使用update语句即可。
  • @Shadow 你的意思是不要使用两个不同的语句进行选择然后更新?相反,您建议使用一种说法?

标签: php mysql hash


【解决方案1】:

如果我的理解正确,您只需要一个子查询:

UPDATE check SET status=1, found=1 WHERE hash IN (SELECT hash FROM actual)

我没有足够的数据来进行有意义的性能比较 - 试试看。

编辑: 通过查看 PHP 解决方案对需求有了更清晰的了解,这里有一个更新的查询:

UPDATE `check` SET status=1, found=(hash IN (SELECT hash FROM actual))  WHERE status=0 

注意:

  • actual.hash 进行索引很重要,否则搜索actual 表将需要很长时间。
  • 根据check 中选中行和未选中行之间的平衡,可能也值得索引check.status。如果大多数行未选中,则不会有任何好处,但如果只有少数未选中的行,它可能会很好地工作。写入索引表可能会慢得多。您需要对自己的数据集进行试验才能找到答案。

【讨论】:

  • 我更新了我的问题,你能告诉我如何做类似UPDATE check SET status=1, found=1 WHERE hash IN (SELECT hash FROM actual) AND status=0 Update found=1 只有在找到匹配项时才会更新 status=1 以便我不'不检查重复。
【解决方案2】:

使用多表 UPDATE 而不是IN ( SELECT ... )

还有

  • 什么版本的 MySQL?
  • 请提供SHOW CREATE TABLE。我们需要查看引擎、索引、数据类型等。
  • SHOW VARIABLES LIKE 'innodb_buffer_pool_size';

“崩溃”是什么意思?重启? mysqld死了?或者只是查询需要很长时间?

一旦我们优化了查询,如果它仍然太慢,我将分阶段向您展示如何做到这一点。这可能涉及直接编写 SQL,而不是通过 Django。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多