当前位置:  开发笔记 > 后端 > 正文

缓存/重用MySQL中的子查询

如何解决《缓存/重用MySQL中的子查询》经验,为你挑选了1个好方法。

我有一个非常复杂的MySQL查询,包括使用相同的子查询三次.MySQL实际上会运行子查询三次吗?(这是一个昂贵的.)如果是这样,有没有办法告诉MySQL保存或缓存结果,所以它不会这样做?我可以将数据保存在一个大型数组中,然后将其重新提供给MySQL,但我宁愿不将它移出并重新进入数据库.

这是三次出现的子查询:

SELECT id FROM programs 
WHERE submitter_id=32 AND id in (
    SELECT id FROM programs 
    WHERE feed_id=2478 AND id in (
        SELECT program_id FROM playlist_program_map 
        WHERE playlist_id=181)))

这是查询出现的完整查询的示例:

SELECT object_id, programs.created AS created, 
MATCH(text) AGAINST ('excellent ' IN BOOLEAN MODE) AS relevance 
FROM comments_programs USE INDEX (text) 
LEFT JOIN programs ON programs.id=object_id 
WHERE object_id IN (
    SELECT id FROM programs 
    WHERE 1 AND id IN (
        SELECT id FROM programs 
        WHERE submitter_id=32 AND id in (
            SELECT id FROM programs 
            WHERE feed_id=2478 AND id in (
                SELECT program_id FROM playlist_program_map 
                WHERE playlist_id=181)))) 
AND MATCH(text) AGAINST ('excellent ' IN BOOLEAN MODE)>0)

UNION (

SELECT object_id, programs.created AS created, 
MATCH(text) AGAINST ('excellent ' IN BOOLEAN MODE) AS relevance 
FROM descriptions_programs USE INDEX (text) 
LEFT JOIN programs ON programs.id=object_id 
WHERE object_id IN (
    SELECT id FROM programs 
    WHERE 1 AND id IN (
        SELECT id FROM programs 
        WHERE submitter_id=32 AND id in (
            SELECT id FROM programs 
            WHERE feed_id=2478 AND id in (
                SELECT program_id FROM playlist_program_map 
                WHERE playlist_id=181)))) 
AND MATCH(text) AGAINST ('excellent ' IN BOOLEAN MODE)>0 AND current=1 ) 

UNION (

SELECT object_id, programs.created AS created, 
MATCH(text) AGAINST ('excellent ' IN BOOLEAN MODE) AS relevance 
FROM titles_programs USE INDEX (text) 
LEFT JOIN programs ON programs.id=object_id 
WHERE object_id IN (
    SELECT id FROM programs 
    WHERE 1 AND id IN (
        SELECT id FROM programs 
        WHERE submitter_id=32 AND id in (
            SELECT id FROM programs 
            WHERE feed_id=2478 AND id in (
                SELECT program_id FROM playlist_program_map 
                WHERE playlist_id=181)))) 
AND MATCH(text) AGAINST ('excellent ' IN BOOLEAN MODE)>0 AND current=1;

Quassnoi.. 8

看看EXPLAIN EXTENDED说了什么.

如果它说DEPENDENT SUBQUERYUNCACHEABLE SUBQUERY,那么每次使用它时都会重新评估.

如果子查询使用会话变量或是相关子查询,则会发生这种情况.

如果没有,它很可能会被缓存.

如果你的情况不会缓存子查询,它将在每个UNION'ed集中重新评估.

但是,你的子查询似乎太复杂了.你为什么不用它:

SELECT id
FROM   playlist_program_map ppm, programs p
WHERE  ppm.playlist_id = 181
       AND p.id = ppm.program_id
       AND submitter_id = 32
       AND feed_id = 2478

如果您有索引playlist_program_map (playlist_id),则此查询应该像魅力一样工作.

你能告诉我另外两件事吗:

    有多少行,有playlist_program_map多少个DISTINCT playlist_id值?

    有多少行,有programs多少DISTINCT submitter_id, feed_id对?

根据您的评论,我可以得出结论,平均每个10 programsplaylist,每对200 programs(submitter, feed).这意味着您的索引playlist_program_map更有选择性(submitter, feed),并且playlist_program_map必须在连接中处于领先地位.

您的案例中的全文索引似乎也不是非常有选择性,因为您需要加入2,000,000个中的10个程序.

您最好尝试以下方法:

SELECT object_id, programs.created AS created
FROM   playlist_program_map ppm, programs p, comments_programs cp
WHERE  ppm.playlist_id = 181
       AND p.id = ppm.program_id
       AND p.submitter_id = 32
       AND p.feed_id = 2478
       AND cp.object_id = p.id
       AND cp.text REGEXP 'excellent'

,并对所有三个表重复此操作.



1> Quassnoi..:

看看EXPLAIN EXTENDED说了什么.

如果它说DEPENDENT SUBQUERYUNCACHEABLE SUBQUERY,那么每次使用它时都会重新评估.

如果子查询使用会话变量或是相关子查询,则会发生这种情况.

如果没有,它很可能会被缓存.

如果你的情况不会缓存子查询,它将在每个UNION'ed集中重新评估.

但是,你的子查询似乎太复杂了.你为什么不用它:

SELECT id
FROM   playlist_program_map ppm, programs p
WHERE  ppm.playlist_id = 181
       AND p.id = ppm.program_id
       AND submitter_id = 32
       AND feed_id = 2478

如果您有索引playlist_program_map (playlist_id),则此查询应该像魅力一样工作.

你能告诉我另外两件事吗:

    有多少行,有playlist_program_map多少个DISTINCT playlist_id值?

    有多少行,有programs多少DISTINCT submitter_id, feed_id对?

根据您的评论,我可以得出结论,平均每个10 programsplaylist,每对200 programs(submitter, feed).这意味着您的索引playlist_program_map更有选择性(submitter, feed),并且playlist_program_map必须在连接中处于领先地位.

您的案例中的全文索引似乎也不是非常有选择性,因为您需要加入2,000,000个中的10个程序.

您最好尝试以下方法:

SELECT object_id, programs.created AS created
FROM   playlist_program_map ppm, programs p, comments_programs cp
WHERE  ppm.playlist_id = 181
       AND p.id = ppm.program_id
       AND p.submitter_id = 32
       AND p.feed_id = 2478
       AND cp.object_id = p.id
       AND cp.text REGEXP 'excellent'

,并对所有三个表重复此操作.

推荐阅读
N个小灰流_701
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有