【问题标题】:Is there optimization for this SQL query?此 SQL 查询是否有优化?
【发布时间】:2013-05-16 20:53:26
【问题描述】:

此查询运行良好,但执行时间过长。它在 xampp localhost 上运行。

只是我想选择word=“somthing”和word的webpage.id != "另一个东西"

我的意思是,如果您在 Google 上搜索,您可以使用该快捷方式 “蟒蛇-猫” 这意味着获取所有包含单词“python”但不包含单词“cat”的链接。

SELECT webpage.title, word.title, word.id, webpage.title, webpage.id, webpage.link, wordpage.wordID, wordpage.id, wordpage.type, wordpage.pageID
FROM SE_word AS word
INNER JOIN se_wordpage AS wordpage ON wordpage.wordID = word.id
INNER JOIN se_webpage AS webpage ON wordpage.pageID = webpage.id
WHERE word.title = "python"

AND webpage.id NOT IN (    
SELECT WP.id
FROM se_webpage AS WP
INNER JOIN se_wordpage AS WOP ON WP.id = WOP.pageID
INNER JOIN se_word AS W ON W.id = WOP.wordID
WHERE W.title = "cat"
)
GROUP BY webpage.id
ORDER BY webpage.title DESC

这是一个简单的搜索引擎,例如

table se_Word is
**id   |  title**
1   |   "game"
2   |   "java"
3   |   "python"

table se_WebPage is
**id   |  title**
1   |   "www.ABCDEF.com"
2   |   "www.ABCDR.net"
3   |   "www.ABC.com"


table se_WordPage is
**id   |  pageID   |   wordID**
1   |   1   |   1
2   |   2   |   3
3   |   3   |   3
3   |   2   |   1

结果应该是webpage.id = 3

here is创建脚本 有什么优化吗?

提前致谢。

【问题讨论】:

  • 1.提供带有EXPLAIN 的执行计划 2. 提供所有表模式
  • 我已经添加了。谢谢
  • @Strawberry 你的意思是子查询吗?我认为主查询中列的值与子查询的值不同
  • 你都没有添加:1.EXPLAIN 2.SHOW CREATE TABLE
  • @zerkms 这里是创建脚本dl.dropboxusercontent.com/u/41343544/se_db.sql

标签: mysql sql database


【解决方案1】:

使用“not in”很慢。如果您的数据库支持这里的语法,有两种更快的方法。

where not exists
(your subquery)

where webpage.id in
(select id
 from se_webpage
 except
 select id
 from 
 the rest is as per your existing subquery
)

对于某些数据库引擎,您使用关键字“minus”而不是“except”。

【讨论】:

  • MySQL 既不支持 MINUS 也不支持 EXCEPT。
  • 不存在工作正常,但时间附近相同!谢谢老兄
【解决方案2】:

我认为,如果您可以摆脱 NOT IN 部分,那么您应该会看到健康的性能提升。尝试使用这两个等效语句作为如何重写语句的示例。

声明 1:

select ID, PreferredMethods 
from ContactPrefs 
where type='Mail' and 
ID NOT IN 
(select ID from ContactPrefs where type='Email' or type='Phone' or type='Text')

语句 1 等效于语句 2,但语句 2 的性能会更好:

select ID, PreferredMethods from ContactPrefs c1 
left outer join
ContactPrefs c2 on c1.ID=c2.ID
and (c2.type='Email' or c2.type='Phone' or c2.type='Text')
where c1.type='Mail' and c2.id is null

【讨论】:

    【解决方案3】:

    您可能想考虑these lines 的解决方案 - 几个月前由另一个论坛中的某个人提供(我知道,我知道)。

    此外,您的查询的第一部分会更有意义(无论如何对我来说)这样写(注意没有 GROUP BY 子句 - 这是故意的)...

    SELECT DISTINCT p.title p_title
                  , w.title w_title
                  , w.id w_id
                  , p.id p_id
                  , p.link
                  , wp.id
                  , wp.type
               FROM SE_word w
               JOIN se_wordpage wp 
                 ON wp.wordID = w.id
               JOIN se_webpage p 
                 ON p.id = wp.pageID
              WHERE w.title = "python"
    

    【讨论】:

      【解决方案4】:

      我没有测试这个查询,但我认为它可能会完成这项工作。请让我知道它是否可以正常工作。

      根据您的原始查询,我刚刚删除了子查询,在WHERE 子句中添加了“猫”标题,并在GROUP BY 之后添加了一个HAVING 子句来过滤仅选择一次的网页,并且此选择指的是“python”标题。

      我假设您从不将一个给定的单词多次分配给一个给定的网页。

      SELECT 
        webpage.title, 
        word.title, 
        word.id, 
        webpage.title, 
        webpage.id, 
        webpage.link, 
        wordpage.wordID, 
        wordpage.id, 
        wordpage.type, 
        wordpage.pageID
      FROM se_word AS word 
      INNER JOIN se_wordpage AS wordpage 
        ON wordpage.wordID = word.id 
      INNER JOIN se_webpage AS webpage 
        ON wordpage.pageID = webpage.id 
      WHERE word.title IN ("cat", "python") 
      GROUP BY webpage.id 
      HAVING 
        COUNT(webpage.id) = 1 
        AND word.title = "python" 
      ORDER BY webpage.title DESC; 
      

      希望它运作良好并对您有所帮助!再见。

      编辑

      我测试了我的查询(MySQL 5.5.22),它似乎工作正常!这是我的表结构和数据:

      se_word

      ---- -------- |编号 |标题 | ---- -------- | 1 |游戏 | | 2 |爪哇 | | 3 |蟒蛇 | | 4 |猫 | ---- --------

      表格se_webpage

      ---- ------ ------------ ------ --------- |编号 |链接 |标题 |频率 |日期 | ---- ------ ------------ ------ --------- | 1 |空 | aaaaa.com | 0 | 2013-05-15 22:27:40 | | 2 |空 | bbbbb.com | 0 | 2013-05-15 22:27:40 | | 3 |空 | ccccc.com | 0 | 2013-05-15 22:27:40 | | 4 |空 | ddddd.com | 0 | 2013-05-15 22:27:40 | ---- ------ ------------ ------ ---------

      表格se_wordpage

      ---- -------- -------- ------ |编号 |字号 |页ID |类型 | ---- -------- -------- ------ | 1 | 3 | 1 | | | 2 | 3 | 2 | | | 3 | 3 | 3 | | | 4 | 3 | 4 | | | 5 | 4 | 2 | | | 6 | 4 | 4 | | ---- -------- -------- ------

      由于“python”一词是指所有网页,而“cat”一词是指第二个和第四个网页,因此预期的输出(据我理解)应该是第一个和第三个网页(有更多的数据)。所以,查询效果很好!

      输出

      ------------ -------- ---- ------------ ---- ------ ------ -- ---- ------ -------- |标题 |标题 |编号 |标题 |编号 |链接 |字号 |编号 |类型 |页ID | ------------ -------- ---- ------------ ---- ------ ------ -- ---- ------ -------- | ccccc.com |蟒蛇 | 3 | ccccc.com | 3 |空 | 3 | 3 | | 3 | | aaaaa.com |蟒蛇 | 3 | aaaaa.com | 1 |空 | 3 | 1 | | 1 | ------------ -------- ---- ------------ ---- ------ ------ -- ---- ------ --------

      查看列的顺序与查询语句中的顺序相同。

      如果有问题请告诉我。

      【讨论】:

      • HAVING COUNT(webpage.id) = 1 错误 >
      • 我的错,对不起。 HAVING 子句位于 ORDER BY 之前。能否请您再试一次编辑后的查询?
      • 首先非常感谢您的努力,您的代码运行良好,但我的意思是,如果在 Google 上搜索,您可以应用该快捷方式“python -cat”,这意味着获取所有包含单词的链接python 并且不包含单词 cat。你明白了吗?
      猜你喜欢
      • 2016-04-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-29
      • 2021-05-24
      • 1970-01-01
      • 1970-01-01
      • 2021-06-15
      相关资源
      最近更新 更多