MySQL能处理1亿行及以上的数据吗?

3
我运营一个中小型汽车网站,我们正在尝试记录访问者浏览车辆详细页面的次数。我们通过哈希化当前车辆的制造商、型号和邮编(使用md5算法)来实现此目的。然后,我们保留vehicle_count总数,并在哈希匹配时递增该总数。
经过计算,大约有50个制造商,每个制造商有大约50个型号,我们的位置数据库有大约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函数将如何执行。如果/当该表格有几百万行以上时,该表格将如何执行。有人能给出一些见解吗?


7
查询数据会是什么样子?不要忘记 WHERE 子句。 - MonkeyZeus
MySQL完全能够处理这个问题,但为什么不适当地对制造商和型号进行规范化呢? - Mark Baker
3
1)阅读官方文档:http://dev.mysql.com/doc/refman/5.0/en/table-size-limit.html 2)为什么要存储值的哈希?为什么不使用普通字段(make,model,zip,visit_count)的普通表格? 3)查询什么?可能是“select ...”。 - Marc B
由于这个表很小(相对较少的列),有人能猜测一下这个表可能占用的大小吗? - user1050544
1
你有没有考虑使用Google Analytics呢?它运行速度快,是业界标准,而且免费,可以完全满足你的需求。 - h2ooooooo
显示剩余9条评论
1个回答

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;

这样可以避免多个唯一值。您可以使用真实世界的值来创建唯一标识符,而不是“ID”和“Hash”。请注意,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位的。
哈希方法可能有助于查找,但它真的能帮助实际应用吗?这个表似乎跟踪访问者,并且很可能会对其进行分析。索引将有助于SUM()操作(取决于索引的顺序)。例如,如果我想找到“Honda”或“Honda Civic”页面的访问者总数,则可以使用多列索引轻松完成。

我认为将这三个字段中的每一个转换为外键也可以节省一些空间! - halfer
你有任何具体的证据证明这样做更快吗?这是直接从mysql.com上摘录的:作为复合索引的替代方案,您可以引入一列,该列基于其他列的信息进行“哈希”。如果此列较短、相对唯一且已建立索引,则可能比许多列上的“宽”索引更快。在MySQL中,使用此额外列非常容易:SELECT * FROM tbl_name WHERE hash_col=MD5(CONCAT(val1,val2)) AND col1=val1 AND col2=val2; 这不就是我在PHP代码中所做的吗...它说它更快? - user1050544
@user1050544,谢谢,我已将您的方法添加到答案中。抱歉没有证据,但我相信始终需要进行实际测试才能确定。 - stomo21

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接