2009-09-08 53 views
1

我有一个大的MySQL InnoDB表(大约1百万条记录,每周增加300K)让我们来说说博客文章。这个表格有一个带有索引的url字段。在数据库中使用MD5(URL)而不是URL用于WHERE

通过添加新记录,我正在检查具有相同网址的现有记录。下面是查询的样子:

SELECT COUNT(*) FROM `tablename` WHERE url='http://www.google.com/'; 

当前系统每秒产生大约10-20个查询,这个数量将会增加。我正在考虑通过添加URL的MD5散列的其他字段来提高性能。

SELECT COUNT(*) FROM `tablename` WHERE md5url=MD5('http://www.google.com/'); 

所以它会更短,并且具有恒定的长度,这对于索引来说比URL字段更好。你们对此有何想法?是否有意义?

我的朋友的另一个建议是使用CRC32而不是MD5,但我不确定CRC32的结果有多独特。让我知道你对这个角色的看法。

更新:URL列对每一行都是唯一的。

回答

4

在URL上创建一个非聚集索引。这将让你的SQL引擎在内部完成所有的优化,并且会产生最好的结果!

如果您在VARCHAR列上创建索引,则SQL将在内部创建一个哈希值,并且使用索引可以将性能提高一个数量级甚至更多!

此外,东西要记住,如果你只是检查URL是否存在,是某些SQL产品会产生更快的结果,像这样的查询:

IF NOT EXISTS(SELECT * FROM `tablename` WHERE url='') 
    -- return TRUE or do your logic here 
+1

我认为“非群集”是SQL Server的术语 - 不应该只是作为索引读取吗? – 2009-09-08 17:12:18

+0

非聚集索引是数据上的“虚拟”索引,而聚簇索引是数据上的物理索引。每个表只能有一个聚簇索引,而在同一个表上可以有多个非聚簇索引 – 2009-09-08 17:15:38

+0

同意,NC索引将获得与添加MD5或其他哈希相同或相似的性能。如果每个网址的表名记录比例很高,我会考虑使用两个表结构,其中唯一的网址保存在tblUrls中,而tablename只存储相应的键。这可能会稍微提高插入性能,但也会降低存储要求并具有其他一些优点,具体取决于底层应用程序。 – mjv 2009-09-08 17:21:24

0

我认为CRC32对于这个角色实际上会更好,因为它更短,并且可以节省更多的SQL空间。如果您收到很多查询,那么对象是否可以节省空间?如果它能完成这项工作,我会说去做。

尽管由于它只有32位,并且长度较短,所以它不像MD5那样独特。你将不得不决定你是否想要独特的,或者如果你想节省空间。

我仍然认为我会选择CRC32。

我的系统每秒钟产生大约4k个查询,我使用CRC32作为链接。

+0

您可以将完整的url始终存储在单独的列中,并要求MySQL比较两者:相同的CRC32和相同的完整URL。 – 2009-09-09 02:33:19

+0

请试试这个,谢谢! :P – Homework 2009-09-09 18:24:06

-1

如果趋势是在选择语句的结果相当高,另一种解决方案是有一个单独的表格来跟踪计数。显然,使用这种技术有很高的惩罚性,但如果这个特定的查询是一个常见的查询并且速度太慢,这可能是一个解决方案。

这个解决方案涉及显而易见的权衡,您可能不希望在插入新记录的每个单独插入之后更新此第二个表,因为这会降低插入速度。

0

使用内置的索引永远是最好的,或者你应该自愿加入到他们的基本代码反正;)

当使用散列,创建散列和URL 2列索引。如果您只选择索引中的第一对字母,它仍然会完成匹配,但它不会索引更多的前几个字母。

事情是这样的:

INDEX(CRC32_col, URL_col(5)) 

无论是哈希会在这种情况下工作。这是对空间与速度的权衡。

此外,该查询会快很多:

SELECT * FROM table WHERE hash_col = 'hashvalue' AND url_col = 'urlvalue' LIMIT 1; 

这将找到的第一个值,并停止。比COUNT(*)计算找到许多匹配要快得多。

最好的选择是为每个变体和基准测试用例。

-1

如果你选择一个散列,你需要考虑到collissions。即使是像MD5这样的大散列,你也必须考虑meet-in-the-middle概率,更好的称为birthday attack。对于像CRC-32这样的较小的散列,冲突概率将非常大,并且您的WHERE必须指定散列完整的URL。

但我得问,这是花费你的努力的最佳方式?还有没有其他的优化?除非您有明确的指标和测量指示此问题是系统的瓶颈,否则您可能会做得过早优化。毕竟,这种寻求是数据库优化的(所有这些),并且通过做一些类似哈希的事情可能会降低性能(例如,由于哈希与URL有不同的分布,因此索引可能会变得碎片化)。

0

大多数SQL引擎不是在内部使用哈希函数来进行文本列搜索吗?

0

如果您打算使用散列键并且担心碰撞,请使用两个不同的散列函数并连接两个散列值。

但即使您这样做,您也应该始终将原始关键值存储在该行中。

相关问题