我正在开发“在线流媒体”项目,我需要一些帮助来构建数据库以获得最佳性能。目前我有一个表格,其中包含播放器的所有相关信息,包括文件,海报图片,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其中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这样的大型网站如何构建他们的数据库?
答案 0 :(得分: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。
这会快得多,因为数据库永远不需要查看每一行来处理查询。索引的成本:
对于您的查询,我建议您在2列上创建索引。使它们成为同一索引的一部分,而不是两个单独的索引:
create index ix_dle_playerFiles__post_id_type on dle_playerFiles (post_id, type)
高效工作的注意事项:
答案 1 :(得分:1)
如果我正确阅读了您的持续时间,则运行查询似乎需要0.04630675(秒?),而不是0.5秒。
无论如何,正确的索引可以减少返回查询结果所需的时间。根据您的查询SELECT * FROM dle_playerFiles where post_id in ('7000') AND type='1'
,建议使用post_id
和type
的索引。
此外,如果您绝对要求返回所有字段,请使用您需要的字段的单独列引用,而不是*
。字段越少,查询返回的速度就越快。
优化查询的另一种方法是确保在主/外键和索引字段中使用可能的最小数据类型 - 尤其。如果bigint
,int
或更好,mediumint
仍然可以smallint
或tinyint
,则永远不要使用{{1}}或{{1}}。从来没有永远在PK或FK中使用文本字段,除非你没有其他选择(这是一个DB设计犯罪过于经常IMO,即使是有足够的培训和经验的人知道更好) - 你最好使用最小的精确数字类型。所有这些都对存储大小产生了积极影响。