优化连接查询,需要“过滤”不同的

Posted

技术标签:

【中文标题】优化连接查询,需要“过滤”不同的【英文标题】:Optimize join query with need to "filter" for distinct 【发布时间】:2021-05-16 15:52:30 【问题描述】:

我想知道我还能优化多少相对简单的查询。为了抽象,我只有两个表,albums,以专辑 ID 和专辑标题,另一个是 albums_genre,以专辑 ID 和专辑类型为列。

我的查询如下:

SELECT DISTINCT album_title
from albums
INNER JOIN albums_genre
ON albums.album_id = albums_genre.album_id AND (genre = 'Metal' OR genre = 'Jazz')

对我来说问题是,在albums 表中,1 id 可能与多个专辑标题匹配,我正在尝试找到一种方法来减少 distinct 所需的时间,因为它需要一半以上的整体时间。我正在使用 Microsoft DB。

提前感谢大家!

【问题讨论】:

你为什么要distincting,也许你的join应该是exists?也许genre 过滤器可以转换为union all,但是如果没有关于索引的信息就很难说。为了获得适当的性能帮助,您需要提供完整查询、表和索引定义(最好是create/insert语句),并通过brentozar.com/pastetheplan共享查询计划 您的餐桌设置听起来不合理。您的专辑表应该有一个专辑 ID、专辑名称,然后还有其他 ID,如流派 ID、艺术家 ID 等。第二个表“album_genres”将只有一个专辑流派 ID 和与这些流派 ID 一起使用的描述。换句话说,每个表都应该避免重复信息。通过将 album_ID 放入您的流派表中,流派表最终将重复显示相同的流派信息。那是不正确的设计。您可能会在此处阅读“3NF”=guru99.com/database-normalization.html 只需在流派列上放一个索引就可以了 仅供参考,“Microsoft DB”可能是 SQL Server 或 MS Access - 有助于明确。 【参考方案1】:

一个更优化的方法是使用exists 而不是 join 用于您的案例场景,您也可以使用 in 而不是 Or 来检查列中的多个值:

SELECT album_title
from albums a
where exists ( 
     select 1 from albums_genre g 
     where a.album_id = g.album_id
     and genre in ('Metal', 'Jazz') 
)

【讨论】:

【参考方案2】:

第一步是使用exists编写查询:

SELECT a.album_title
FROM albums a
WHERE EXISTS (SELECT 1
              FROM albums_genre ag
              WHERE ag.album_id = a.album_id AND
                    ag.genre IN ('Metal', 'Jazz')
             );

然后,为了提高性能,您需要在albums_genre(album_id, genre) 上建立索引。仅在 (album_id) 上的索引可能也足够好。

请注意,性能提升来自于删除外部查询中的聚合/不同的删除。

【讨论】:

感谢您的回答。我试过你的查询,它确实快得多(大约 50%),但与我原来的查询相比,它给了我更多的结果。它给了我超过 20k 行而不是 19742 行。在albums 表中,存在重复的标题(相同的标题,不同的专辑 ID),我认为这是导致问题的原因,你有任何想法如何改进查询? @AndreasTzalakas。 . .我认为这产生了正确的结果,因为它为每个album_id 产生了一个单独的行。但是,如果您真的认为album_titles 是独一无二的,您可以使用select distinct a.album_title【参考方案3】:

最初查询速度变慢是在“或”上,将“或”转换为子查询,见下文。而不是不同的使用组

SELECT album_title
from albums
INNER JOIN (select album_id from albums_genre where genre in ('Metal' 
,'Jazz'))albums_genre
ON albums.album_id = albums_genre.album_id 
group by album_title

【讨论】:

以上是关于优化连接查询,需要“过滤”不同的的主要内容,如果未能解决你的问题,请参考以下文章

mysql中,如何向测试人员介绍连接查询和子查询的优劣势?

使用笛卡尔连接优化 sql 查询

MySQL多表查询 三表查询 连接查询的套路

需要帮助优化外连接 SQL 查询

Flask-SQLAlchemy 左外连接过滤查询

使用 WHERE 子句中的过滤器优化 OUTER JOIN 查询。(查询规划器)