0

我的网站显示了不同主题的链接集合。这些链接分为两种类型:网络和图像。我的数据库将有数百万(可能超过一千万)这些记录。当页面加载时,我需要向用户显示该页面特定主题的 Web 和图像链接。所以第一个问题是:

  1. 我是创建两个单独的较小的表,每个表用于 Web 和图像链接,然后对每个表进行查询,还是为两者创建一个巨大的表(具有正确的索引)并进行一次查询。我将在哪里获得更好的性能?如果一个表和一个查询更有效,那么我的下一个问题是:

  2. 细分这两种类型以进行演示的最有效方法是什么?我应该使用group by,还是应该使用 php 将我的结果数组分为两种类型?

蒂亚!

4

4 回答 4

3

您可以对所有对象使用一个表,或者对链接或网站使用一个表来获得类似的性能。如果您有两个单独的表,则对结果进行 UNION 将返回您需要的所有结果。

划分结果的主要原因是它们是否真的不同(从您的应用程序的角度来看)。也就是说,如果您最终要使用很多查询,例如

select * from objects where type='image';

那么有两个表可能是有意义的。

然后使用 group by 不是对不同结果进行分组的一种方式,而是一种聚合它们的方式。

因此,例如,您可以使用

select type, count(*) from objects group by type

要得到

| image |  100000 |
| web   | 2000000 |

但它不会返回分离的对象。要将它们“分组”,您可以对每个使用查询,或者使用排序,然后在应用程序中使用逻辑来划分结果。

于 2013-03-03T10:39:21.127 回答
1

这取决于 web 数据如何接近 img 数据。如果数据基本上是由链接组成的,那么一个表更合适,有一个列来区分网络和数据(以后可能还有其他的,比如 css、js ......)

Links: (id, link, type)

在类型类型链接上添加索引将有助于分组(按类型)和匹配搜索(类型,链接)。

但是,如果 web 和 img 数据的不同之处在于您不想混合使用苹果和橙子,例如

Web: (wid, wlink, rating, ...)
Img: (iid, ilink, width, height, mbsize, camera, datetaken, hasexif...)

在这种情况下,除了链接之外,两个表都没有太多共同点。图像链接和网络链接不同,当两种数据都具有相同的链接时,甚至没有“增益”。另一个优点(一个表也可以,但在这里更有意义)是将两种数据链接到另一个表中

 Relations: (wid,iid)

这允许维护网站和图像之间的关系,因为一个图像可能被多个网站使用,而网站使用多个图像。索引上wid和上iid

我的偏好是这两个表(带有可选的关系链接)。

关于来自 PHP 的查询,使用UNION您可以在一次查询中从两个表中获取数据。

于 2013-03-03T10:57:49.637 回答
1

您可能会从一张表中获得稍微更好的性能,但此决定应主要取决于数据或约束的性质是否不同。

您必须做出另一个(从性能角度来看更重要的)决定:您希望如何对数据进行集群(所有InnoDB 表都是集群的)?

如果您想在获取给定页面的所有链接时获得出色的性能,请使用标识关系,在链接表中生成自然键:

在此处输入图像描述

LINK 表实际上只是一个 B 树,页 PK 1在其前沿,它将属于同一页的行物理地组合在一起。以下查询可以通过简单的索引范围扫描和最少的 I/O 来满足:

SELECT URL
FROM LINK
WHERE PAGE_ID = <whatever>

如果您使用单独的表,则只能有两个不同的查询。许多客户端 API 支持在单个数据库往返中执行两个查询。如果 PHP 没有,您可以 UNION 两个查询以节省一个数据库往返:

SELECT *
FROM (
    SELECT 1 LINK_TYPE, URL
    FROM IMAGE_LINK
    WHERE PAGE_ID = <whatever>
    UNION ALL
    SELECT 2, URL
    FROM WEB_LINK
    WHERE PAGE_ID = <whatever>
)
ORDER BY LINK_TYPE

上面的查询会给你...

LINK_TYPE  URL
1          http://somesite.com/foo.jpeg
1          http://somesite.com/bar.jpeg
1          http://somesite.com/baz.jpeg
...
2          http://somesite.com/foo.html
2          http://somesite.com/bar.html
2          http://somesite.com/baz.html
...

...这将很容易在客户端级别分离。

如果您没有使用单独的表,您可以在客户端级别通过它们的扩展名来分隔 URL,或者在 LINK PK 中引入一个附加字段:{PAGE_ID, LINK_TYPE, URL},这应该会使以下查询非常有效:

SELECT LINK_TYPE, URL
FROM LINK
WHERE PAGE_ID = <whatever>
ORDER BY LINK_TYPE

请注意,PK 中的字段顺序很重要,因此将 LINK_TYPE 放在末尾会阻止 DBMS进行索引范围扫描。


1不管它是什么;我只是用了PAGE_ID一个例子。

于 2013-03-03T14:03:27.903 回答
0

我是创建两张单独的小桌子还是一张大桌子?

去一张桌子。

细分这两种类型以进行演示的最有效方法是什么?

取决于特定的搜索条件。

于 2013-03-03T10:27:24.227 回答