spi*_*der 12 mysql database-design primary-key
这是存储网站地址和网页网址的最佳主键?
为了避免使用自动增量id(它与数据没有真正联系),我设计了使用URL的SHA1签名作为主键的模式.
这种方法在很多方面都很有用:例如,我不需要从数据库中读取last_id,因此我可以准备计算密钥的所有表更新,并在单个事务中进行真正的更新.没有约束违规.
无论如何,我读了两本书,告诉我我错了.在"高性能MySQL"中,据说随机密钥对DB优化器不利.此外,在Joe Celko的每本书中,他都说主键应该是数据的一部分.
问题是:URL的自然键是...... URL本身.事实是,如果一个站点很短(www.something.com),那么am URL没有强制限制(参见http://www.boutell.com/newfaq/misc/urllength.html).
考虑一下我必须存储(并使用)数百万个.
那么哪个是最好的钥匙?自动增量ID,网址,网址哈希?
小智 16
您需要一个自动增量数字主键.对于需要传递ID或联接其他表的时间(例如,URL的可选属性),您需要一些小而且数字的东西.
至于你想要的其他列和索引,它一如既往地取决于你将如何使用它们.
存储每个URL的散列的列对于几乎所有使用大量URL的应用程序来说都是一个很好的主意.它使得通过其全文选择一个URL的速度与它将获得的速度一样快.第二个优点是,如果您将该列设置为UNIQUE,则无需担心使存储实际URL的列唯一,您可以使用REPLACE INTO和INSERT IGNORE作为简单,快速的原子写操作.
我想补充一点,使用MySQL的内置MD5()函数就可以了.它唯一的缺点是专门的攻击者可以强制进行冲突,我很确定你不关心.例如,使用内置函数可以更轻松地实现某些类型的连接.通过网络传递完整的URL可能会慢一点("SELECT url FROM urls WHERE hash = MD5('verylongurl')"而不是"WHERE hash ='32charhexstring'"),但你可以选择如果你想要这样做.除非你能想出一个MD5()会让你失望的具体场景,否则请随意使用它.
难以理解的问题是,您是否以及如何以非完整文本的方式查找URL:例如,您是否要在任何"bar.com"主机上找到以"/ foo"开头的所有URL?虽然"LIKE'%bar.com%/ foo%'"将用于测试,但它将在规模上惨败.如果您的需求包含类似的内容,您可以采用创造性的方法来生成针对您需要的数据类型的非UNIQUE索引...对于初学者,可能是domain_name列.你必须从你的应用程序填充这些列,几乎可以肯定(触发器和存储过程比它们在这里值得多麻烦,特别是如果你关心性能 - 不要打扰).
好消息是关系数据库对于这类事情非常灵活.您始终可以添加新列并在以后填充它们.我建议初学者:int unsigned auto_increment主键,唯一散列字符(32)和(假设64K字符就足够了)文本url.