假设我有一个带有长变量(URL,如 100-250 个字符)的大表(100000+ 个条目)。将 MD5 散列作为旁边的单独字段用于从表中获取单行对于更好的性能是否有意义?
SELECT * FROM `urls` WHERE `url` = 'http://long-phrase...' LIMIT 1;
或者
SELECT * FROM `urls` WHERE `url_md5` = MD5('http://long-phrase...') LIMIT 1;
我想使用 INDEX 就足够了,这就是为什么,在下雪的星期天以平淡的心情写的:
数据库将其行一个接一个地存储在文件中:
id url name descr visited
1 http://... somewhere i like it 2013-01-01
2 http://... wherever i dislike it 2013-01-02
...
您将在磁盘上拥有这些数据,大致如下:
[s:35:http://...s:9:somewhere...][s:45:http://...s:9:wherever...][...]
一堆字节,很多。如果您要求数据库搜索给定术语,则数据库必须通过扫描文件来扫描“行”并应用搜索词。假设您有 100 万行,数据库必须扫描 100 万行。假设您要在行中搜索“url”字段。假设您缩短(或扩展,执行“http://goo.gl/P0Gwz”的 md5)字符串后,“搜索”变得更容易:您仍然需要搜索 100 万行。
另一方面,如果您只是可以搜索 ORDERED 行列表,那真的会加快速度。因此,假设数据库现在存储了在您插入行时未排序但按“url”字段排序的行。现在,只要您插入新行,数据库就必须重新排序磁盘上所有存储的字节。因为,您现在可以更快地搜索,但 INSERT 操作要慢得多。并且不要忘记:明天您要搜索“descr”字段。现在怎么办?重新排序整个文件?保留文件的 2 个副本?
一种更好的方法是使用寄存器,一个有序列表,其中包含在哪里可以找到“行”的参考。这个想法与现实世界的图书馆一样古老:只需将书籍一个接一个地放在书架上,给它编号,然后创建列表:一个按作者姓名排序,一个按出版年份排序,一个按标题等。想要搜索作者 选择作者注册,通过类似二分搜索的方法扫描名称(如果此人很聪明),获取书号,上书架并快速拿起书.
该“注册”事物也称为“索引”:对磁盘上引用行位置的引用的有序列表:
[s:35:http://...s:9:somewhere...][s:45:http://...s:9:wherever...][...]
^ ^ ^
| | |
| | |
i1 -------------------------------- ^ |
i2 ------------------------------------------------------------------>
i3 -^ |
i100 -------------------------------------------------------------^
例如,您现在可以检查i50
您的搜索词是否匹配。如果索引函数指向大于 50 的值,则在下一轮检查 i75,如果小于 50,则检查 i25,依此类推。
给你数字:给定 100 万行,你搜索“url”字段,你必须扫描:
明天你将有 200 万行。现在您必须不使用 INDEX 扫描超过 200 万行,并且您必须最多扫描 20 次才能找到正确的记录或什么也没有。数百万次字符串比较与 20 次比较。您会看到使用 INDEX 的影响有多大。
在此处阅读有关该主题的更多信息: