Php 如何使此SQL查询最有效?

Php 如何使此SQL查询最有效?,php,mysql,sql,database-design,Php,Mysql,Sql,Database Design,我正在制作一个由用户添加大量图片的网站 我想从该池中随机选择一个图像,并将其显示给用户,但我想确保该用户以前从未见过该图像 所以我想:当一个用户查看一个图像时,我在MYSQL中插入一行,对每个条目都说“这个用户在(时间)观看了这个图像”。 但问题是,因为可能有很多用户和很多图像,这个表可以很容易地快速增长到数万个条目 因此,也可以这样做: 我正在考虑为每个用户插入一行,在一个字段中,插入一个数组,该数组包含用户观看过的所有id的图像 我甚至可以对阵列执行此操作: base64_编码(gzcomp

我正在制作一个由用户添加大量图片的网站

我想从该池中随机选择一个图像,并将其显示给用户,但我想确保该用户以前从未见过该图像

所以我想:当一个用户查看一个图像时,我在MYSQL中插入一行,对每个条目都说“这个用户在(时间)观看了这个图像”。 但问题是,因为可能有很多用户和很多图像,这个表可以很容易地快速增长到数万个条目

因此,也可以这样做: 我正在考虑为每个用户插入一行,在一个字段中,插入一个数组,该数组包含用户观看过的所有id的图像

我甚至可以对阵列执行此操作: base64_编码(gzcompress)(序列化($array)

然后: 取消序列化(gzuncompress(base64_解码($array))

你觉得我该怎么办? 编码/解码功能是否足够快,或者至少比我在文章开头描述的传统方式快

这种压缩是否足以将大块数据存储到一个数据库字段中?(想象一下,如果用户查看了数千张图像?)


非常感谢

您应该创建一个新表
UserImageViews
,其中包含列
user\u id
image\u id
(此外,您可以添加有关视图的更多信息,例如日期/时间、IP和浏览器)


这将产生类似“用户看到(未看到)哪些图像”的查询更快。

您应该使用表。将数据序列化到数据库中的单个字段是一种不好的做法,因为DBMS不知道该数据表示什么,并且不能用于任何查询。例如,如果您想查看哪些用户查看了图像,您将无法仅使用SQL

顺便说一句,数万条条目并不多。我们开发的主要应用程序有多个表,其中包含数十万条记录,而我们并没有那么大。一些web应用程序有数百万行的表。不要担心“数据太多”除非它开始成为一个问题,否则这个问题的解决方案将是复杂的,甚至可能会减慢您的查询速度,直到您得到那么多的数据

编辑:哦,是的,对那些100k+表的连接在不到一秒钟的时间内发生。只是给你一些透视图

在一个字段中,我插入一个数组,其中包含所有id


在几乎所有情况下,像这样序列化值都是不好的做法。让数据库做它设计用来做的事情——高效地处理大量数据。只要确保交叉表在用户字段上有一个索引,检索用户看到的图像列表将不会是一项代价高昂的操作,而不管表中的f行。数万个条目不算什么。

我并不认为数万行对数据库查找是个问题。我建议使用第一种方法而不是第二种方法

我想从这个池中随机选择一个图像,并显示它 给用户,但我想确保该用户从未见过 这是以前的照片

值得一提的是,这不是一个随机算法;这是一个洗牌算法。(知道这一点,当你需要更多的细节时,谷歌会变得更容易。)但这不是你最大的问题

所以我在想:当用户查看图像时,我会排一行 在MYSQL中插入“此用户在 (时间)“每一个条目

好主意。在您的案例中,使用一个表来存储用户看到特定图像的事实是有意义的。除非我错过了什么,否则您不需要存储时间。(而且您可能不应该这样做。它似乎没有任何有用的商业用途。)这样的事情应该可以很好地工作

-- Predicate: User identified by [user_id] has seen image identified by
-- [image_filename] at least once.
create table images_seen (
  user_id integer not null references users (user_id),
  image_filename not null references images (image_filename),
  primary key (user_id, image_filename)
);
测试它并查看的输出。如果您需要对图像\u文件名进行二级索引

create index images_seen_img_filename on images_seen (image_filename);
这仍然不是你最大的问题

最大的问题是您没有亲自测试。如果您知道任何脚本语言,您应该能够在几分钟内生成10000行进行测试。如果您这样做了,您会发现这样的表即使有几百万行,也会运行良好

在回答StackOverlow上的问题之前,我有时会生成数百万行来测试我的想法


学习生成大量随机数据(ish)用于测试的数据是数据库和应用程序开发人员的一项基本技能。

您好,谢谢您的回答。如果表中有10k+行,您认为这种方法对数据库来说会非常密集吗?谢谢编辑:我得到了下面的答案。无论如何,谢谢!不一定,如果您有索引的话。这就是RDBMS为数据库设计的或者。如果使用“一个字段中有多个数据”的方法,情况会更糟。嗨,Ryan,谢谢你的建议。因为我在localhost上,所以其中只有几百行,我的查询只需要不到0.01秒。在我看来,一秒钟对于一台计算机来说似乎是永恒的:)但是我会认真考虑你的建议。谢谢你。你怎么知道用户确实“看到”了这张图片?随机的可能就足够了。:)你是如何选择随机图像的?嗨,Alex,谢谢你的回答。然后我会选择image\u id/user\u id方法。嗨,Catcall,谢谢你的精彩帖子,谢谢你让我知道解释的存在。我想选择user\u id作为主键,但为什么你的建议是:“主键?”(用户id,图像文件名)“?谢谢lot@eric01:如果“user_id”是主键中的唯一列,则每个用户只能存储一个图像文件名。哦,好的,我的第一个想法是,为了每个用户存储多个图像文件名,我必须使用另一个名为“id”的列作为主键(自动递增)然后在第二列显示user_id,在第三列显示filename.B