我有一个大型的艺术家,专辑和曲目的数据库.这些项目中的每一个可以具有通过胶合表(track_attributes,album_attributes,artist_attributes)分配的一个或多个标签.有几千(甚至十万)标签适用于每个项目类型.
我正在努力完成两项任务,我很难让查询执行得很好.
任务1)获得所有具有任何给定标签(如果提供)的曲目,该艺术家在具有任何给定标签的相册(如果提供)上有任何给定标签(如果提供)).任何一组标签可能不存在(即只有一个曲目标签是有效的,没有艺术家或专辑标签)
变化:结果也可以由艺术家或专辑而不是轨道呈现
任务2)获取应用于先前过滤器的结果的标签列表以及每个给定标签的轨迹数.
我以后是一些一般的指导方法.我已经尝试过临时表,内部连接,IN(),所有我的努力迄今为止导致缓慢的响应.以下结果的一个很好的例子可以在这里看到:http://www.yachtworld.com/core/listing/advancedSearch.jsp,除了它们只有一层标签,我正在处理三个标签.
表结构:
- Table: attribute_tag_groups
- Column | Type |
- ------------+-----------------------------+
- id | integer |
- name | character varying(255) |
- type | enum (track,album,artist) |
- Table: attribute_tags
- Column | Type |
- --------------------------------+-----------------------------+
- id | integer |
- attribute_tag_group_id | integer |
- name | character varying(255) |
- Table: track_attribute_tags
- Column | Type |
- ------------+-----------------------------+
- track_id | integer |
- tag_id | integer |
- Table: artist_attribute_tags
- Column | Type |
- ------------+-----------------------------+
- artist_id | integer |
- tag_id | integer |
- Table: album_attribute_tags
- Column | Type |
- ------------+-----------------------------+
- album_id | integer |
- tag_id | integer |
- Table: artists
- Column | Type |
- ------------+-----------------------------+
- id | integer |
- name | varchar(350) |
- Table: albums
- Column | Type |
- ------------+-----------------------------+
- id | integer |
- artist_id | integer |
- name | varchar(300) |
- Table: tracks
- Column | Type |
- -------------+-----------------------------+
- id | integer |
- artist_id | integer |
- album_id | integer |
- compilation | boolean |
- name | varchar(300) |
你可能应该尝试对你的数据进行非规范化.您的结构针对插入/更新加载进行了优化,但不适用于查询.当我得到它,你的选择查询将比插入/更新查询更多.
例如你可以这样做:
将数据存储在标准化结构中.
创建这样的标准表
- track_id,artist_tags,album_tags,track_tags
- 1,jazz/pop/,jazz/rock,/heavy-Metal/
- or
- track_id,track_tags
- 1,1/2/,1/3,4/
要搜索您可能应该在* _tags列上创建FULLTEXT索引
用SQL查询这个表
- select * from aggregate where album_tags MATCH (track_tags) AGAINST ('rock')
每天重新建立一次表.