0

我正在从事“在线流媒体”项目,我需要一些帮助来构建数据库以获得最佳性能。目前我有一张表,其中包含播放器的所有相关信息,包括文件、海报图片、post_id 等。

+---------------+-------------+------+-----+---------+----------------+
| Field         | Type        | Null | Key | Default | Extra          |
+---------------+-------------+------+-----+---------+----------------+
| id            | int(11)     | NO   | PRI | NULL    | auto_increment |
| post_id       | int(11)     | YES  |     | NULL    |                |
| file          | mediumtext  | NO   |     | NULL    |                |
| thumbs_img    | mediumtext  | YES  |     | NULL    |                |
| thumbs_size   | mediumtext  | YES  |     | NULL    |                |
| thumbs_points | mediumtext  | YES  |     | NULL    |                |
| poster_img    | mediumtext  | YES  |     | NULL    |                |
| type          | int(11)     | NO   |     | NULL    |                |
| uuid          | varchar(40) | YES  |     | NULL    |                |
| season        | int(11)     | YES  |     | NULL    |                |
| episode       | int(11)     | YES  |     | NULL    |                |
| comment       | text        | YES  |     | NULL    |                |
| playlistName  | text        | YES  |     | NULL    |                |
| time          | varchar(40) | YES  |     | NULL    |                |
| mini_poster   | mediumtext  | YES  |     | NULL    |                |
+---------------+-------------+------+-----+---------+----------------+

对于 100k 条记录,查询大约需要 0.5 秒,并且随着我有更多记录,性能会不断下降。

+----------+------------+----------------------------------------------------------------------+
| Query_ID | Duration   | Query                                                                |
+----------+------------+----------------------------------------------------------------------+
|        1 | 0.04630675 | SELECT * FROM dle_playerFiles where post_id in ('7000') AND type='1' |
+----------+------------+----------------------------------------------------------------------+

解释 SELECT * FROM dle_playerFiles where post_id in ('7000') AND type='1';

+----+-------------+-----------------+------+---------------+------+---------+------+-------+-------------+
| id | select_type | table           | type | possible_keys | key  | key_len | ref  | rows  | Extra       |
+----+-------------+-----------------+------+---------------+------+---------+------+-------+-------------+
|  1 | SIMPLE      | dle_playerFiles | ALL  | NULL          | NULL | NULL    | NULL | 61777 | Using where |
+----+-------------+-----------------+------+---------------+------+---------+------+-------+-------------+

如何改进数据库结构?像 youtube 这样的大网站如何构建他们的数据库?

4

2 回答 2

2

通常,当查询时间与行数成正比时,这表明进行表扫描,这意味着对于类似的查询

SELECT * FROM dle_playerFiles where post_id in ('7000') AND type='1'

数据库按字面意思执行,例如遍历每一行并检查它是否符合条件。

对此的典型解决方案是索引,它是一列(或一组列)的预先计算的值列表和具有所述值的行的列表。

如果您在 dle_playerFiles 的 post_id 列上创建索引,那么该索引实际上会显示

1: <some row pointer>, <some row pointer>, <some row pointer>
2: <some row pointer>, <some row pointer>, <some row pointer>
...
100: <some row pointer>, <some row pointer>, <some row pointer>
...
7000: <some row pointer>, <some row pointer>, <some row pointer>
250000: <some row pointer>, <some row pointer>, <some row pointer>

因此,有了这样的索引,上面的查询将简单地查看索引的节点 7000 并知道哪些行包含它。

那么数据库只需要读取 post_id 为 7000 的行,并检查它们的类型是否为 1。

这会更快,因为数据库永远不需要查看每一行来处理查询。指数成本:

  1. 存储空间 - 这是更多数据,必须存储在某个地方
  2. 更新时间 - 数据库自动使索引与表的更改保持同步,这意味着 INSERT、UPDATE 和 DELETE 语句将花费更长的时间,因为它们需要更新数据。对于小而高效的索引,这种折衷通常是值得的。

对于您的查询,我建议您在 2 列上创建一个索引。使它们成为同一索引的一部分,而不是 2 个单独的索引:

create index ix_dle_playerFiles__post_id_type on dle_playerFiles (post_id, type)

对此有效工作的注意事项:

  1. SELECT * 在这里不好。如果要返回每一列,那么数据库必须去表中读取列,因为索引只包含用于过滤的列。如果您真的只需要一两列,请在 SELECT 子句中明确指定它们并将它们添加到您的索引中。不要对许多列执行此操作,因为它只会使索引膨胀。
  2. 函数和类型转换往往会阻止索引的使用。您的 SQL 包装整数类型 post_id 并在引号中键入,因此它们被解释为字符串。数据库可能会觉得不能使用索引,因为它必须转换所有内容。删除引号以获得良好的度量。
于 2013-08-27T23:26:56.450 回答
1

如果我正确阅读了您的持续时间,运行您的查询似乎需要 0.04630675(秒?),而不是 0.5 秒。

无论如何,正确的索引可以减少返回查询结果所需的时间。根据您的查询,建议使用和SELECT * FROM dle_playerFiles where post_id in ('7000') AND type='1'索引。post_idtype

此外,如果您不是绝对要求返回所有字段,请使用您需要的字段的单个列引用,而不是*. 字段越少,查询返回的速度就越快。

优化查询的另一种方法是确保尽可能使用最小的数据类型——尤其是在主/外键和索引字段中。永远不要在 a 时使用 abigint或 an ,或者更好的是, a可以。永远不要在 PK 或 FK使用文本字段,除非您别无选择(这是 IMO 经常犯的数据库设计罪,即使是受过足够培训和经验的人也能更好地了解)-您是使用可能的最小精确数字类型要好得多。所有这些对存储大小也有积极影响。intmediumintsmallinttinyint

于 2013-08-27T23:47:24.810 回答