【问题标题】:Can MySQL handle 100 million+ rows? [duplicate]MySQL 可以处理 1 亿多行吗? [复制]
【发布时间】:2014-06-11 16:57:02
【问题描述】:

我经营一个中小型汽车网站,我们正在尝试记录访问车辆详细信息页面的次数。我们通过散列、md5、当前车辆的品牌、型号和 zip 来做到这一点。然后我们保留一个vehicle_count 总数,如果哈希匹配,则增加它。

运行这些数字后,似乎有大约 50 个品牌,每个品牌有大约 50 个型号,我们的位置 db 有大约 44,000 个唯一的邮政编码。大约 1 亿 + 潜在的唯一哈希

这是创建表:

CREATE TABLE `vehicle_detail_page` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `vehicle_hash` char(32) NOT NULL,
  `make` varchar(100) NOT NULL,
  `model` varchar(100) NOT NULL,
  `zip_code` char(7) DEFAULT NULL,
  `vehicle_count` int(6) unsigned DEFAULT '1',
  PRIMARY KEY (`id`),
  UNIQUE KEY `vehicle_hash` (`vehicle_hash`),
  KEY `make` (`make`),
  KEY `model` (`model`),
  KEY `zip_code` (`zip_code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

这是插入/更新表格的 PHP 代码:

public function insertUpdate($make, $model, $zip)
{
    // set table
    $table = self::TABLE;        
    // create hash
    $hash = md5($make.$model.$zip);

    // insert or update count
    try
    {
        $stmt = $this->db->conn->prepare("INSERT INTO $table
                                                (vehicle_hash, 
                                                    make, 
                                                    model, 
                                                    zip_code)
                                          VALUES
                                                (:vehicle_hash, 
                                                    :make, 
                                                    :model, 
                                                    :zip_code)
                                          ON DUPLICATE KEY UPDATE
                                                    vehicle_count = vehicle_count + 1;");
        $stmt->bindParam(':vehicle_hash', $hash, PDO::PARAM_STR);
        $stmt->bindParam(':make', $make, PDO::PARAM_STR);
        $stmt->bindParam(':model', $model, PDO::PARAM_STR);
        $stmt->bindParam(':zip_code', $zip, PDO::PARAM_STR);
        $stmt->execute();
    } catch (Exception $e)
    {
        return FALSE;
    }

    return TRUE;
}

问题:

  1. MySQL 可以处理这么多行吗?
  2. 有没有人发现这段代码有什么问题,有没有更好的方法来做到这一点?
  3. 查询这些数据会是什么样子?

最大的问题是,一旦这个表增长,上面的 php 函数将如何执行。如果/当该表有几百万行以上时,该表将如何执行。谁能提供一些见解?

【问题讨论】:

  • 有足够的服务器能力和足够的耐心,MySQL 可以处理任何事情......只是速度不是很快
  • What will querying the data be like? 出于对总督的爱,不要忘记WHERE 子句
  • MySQL 完全有能力处理这个问题,但你为什么不正确地规范化制造和模型呢?
  • 1) RTFM: dev.mysql.com/doc/refman/5.0/en/table-size-limit.html 2) 为什么要存储值的哈希值?为什么不只是将 (make,model,zip,visit_count) 作为普通字段的普通表? 3)查询什么?大概是select ...
  • 您是否考虑过改用 Google Analytics?它运行迅速 - 是一个行业标准 - 是免费的,可以做你想做的事。

标签: php mysql bigdata


【解决方案1】:

你也可以完全避免散列。

CREATE TABLE `vehicle_visits` (
  `make` varchar(100) DEFAULT NULL,
  `model` varchar(100) DEFAULT NULL,
  `zip_code` char(7) DEFAULT NULL,
  `vehicle_count` int(11) DEFAULT NULL,
  UNIQUE KEY `make_model_zip` (`make`,`model`,`zip_code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

这样可以避免多个 UNIQUE 值。您可以使用真实世界的值来创建唯一标识符,而不是“ID”和“哈希”。请注意 MySQL 如何使用 3 列来形成唯一索引。

注意:要减小索引的大小,您可以减小品牌和型号列的大小。当然,除非您期望有 100 个字符的品牌和型号名称。如果您担心大小,还可以使用每列的前缀创建索引。

编辑:添加哈希列作为索引方法

作为复合索引的替代方案,您可以引入一列 根据其他列的信息“散列”。如果这 列很短,相当独特,并且有索引,它可能会更快 比许多列上的“宽”索引。 http://dev.mysql.com/doc/refman/5.0/en/multiple-column-indexes.html

您需要进行一些实际测试,看看哪种方法更快。由于数据显示大约 50 个品牌和 50 个型号,因此查找将主要涉及 zip_code 列。索引顺序也有所不同。此外,使用 make(10)、model(10)、zip(7) 等前缀创建索引会创建长度为 27 的索引。另一方面,md5 列将是 32。

hash 方法可能有助于查找,但它真的对现实世界的应用程序有帮助吗?该表似乎跟踪访问者,并且很可能会对其执行分析。该索引将有助于 SUM() 操作(取决于索引的顺序)。例如,如果我想查找“本田”或“本田思域”页面的访问者总数,使用多列索引很容易完成。

【讨论】:

  • 我认为将这三个字段中的每一个都转换为外键也会节省一些空间!
  • 你有什么具体的证据证明速度更快。这直接取自 mysql.com:作为复合索引的替代方案,您可以引入基于来自其他列的信息“散列”的列。如果此列很短、合理唯一且已编入索引,则它可能比许多列上的“宽”索引更快。在 MySQL 中,很容易使用这个额外的列: SELECT * FROM tbl_name WHERE hash_col=MD5(CONCAT(val1,val2)) AND col1=val1 AND col2=val2;这不是我在 php 代码中所做的……它说它更快吗?
  • @user1050544,谢谢,将您的方法添加到答案中。抱歉没有证据,但我相信它总是需要真实世界的测试才能确定。
猜你喜欢
  • 1970-01-01
  • 2015-09-08
  • 1970-01-01
  • 1970-01-01
  • 2013-11-12
  • 2011-04-16
  • 2021-05-01
  • 2015-09-29
  • 1970-01-01
相关资源
最近更新 更多