Mysql 使用或使查询执行缓慢的查询

Mysql 使用或使查询执行缓慢的查询,mysql,sql,performance,conditional-statements,Mysql,Sql,Performance,Conditional Statements,我是一个新手,有一个问题或查询 当我不使用或执行时,执行时间为:0.02秒 SELECT DISTINCT p.*, ht.html_title, ht.html_content, sc.sub_cat_name, sc.main_cat_id, us.username, c.name AS citynam

我是一个新手,有一个问题或查询

当我不使用或执行时,执行时间为:0.02秒

SELECT DISTINCT p.*,
                ht.html_title,
                ht.html_content,
                sc.sub_cat_name,
                sc.main_cat_id,
                us.username,
                c.name AS cityname
FROM   ad_product p,
       ad_html ht,
       ad_catagory_sub sc,
       ad_user us,
       ad_cities c
WHERE  ( ht.ad_id = p.id )
       AND ( sc.sub_cat_id = p.category )
       AND ( us.id = p.user_id )
       AND ( p.category = 216 )
       AND ( p.status = 'active' )
       AND ( c.id = p.city )
       AND ( p.city = 135 )
ORDER  BY p.created_at DESC;
当我在任何条件下尝试时,大约需要4.70秒

SELECT DISTINCT p.*,
                ht.html_title,
                ht.html_content,
                sc.sub_cat_name,
                sc.main_cat_id,
                us.username,
                c.name AS cityname
FROM   ad_product p,
       ad_html ht,
       ad_catagory_sub sc,
       ad_user us,
       ad_cities c
WHERE  ( ht.ad_id = p.id )
       AND ( sc.sub_cat_id = p.category )
       AND ( us.id = p.user_id )
       AND ( p.category = 216
              OR p.parent_category = 216 )
       AND ( p.status = 'active' )
       AND ( c.id = p.city )
       AND ( p.city = 135 )
ORDER  BY p.created_at DESC;
说明:

+----+-------------+-------+------------+-------------+--------------------------------------------------------------------------------+--------------------------+---------+---------------------------+-------+----------+----------------------------------------------------+
| id | select_type | table | partitions | type        | possible_keys                                                                  | key                      | key_len | ref                       | rows  | filtered | Extra                                              |
+----+-------------+-------+------------+-------------+--------------------------------------------------------------------------------+--------------------------+---------+---------------------------+-------+----------+----------------------------------------------------+
|  1 | SIMPLE      | c     | NULL       | const       | PRIMARY                                                                        | PRIMARY                  | 4       | const                     |     1 |   100.00 | Using temporary; Using filesort                    |
|  1 | SIMPLE      | p     | NULL       | index_merge | PRIMARY,id,parent_category,city,user_id_2,category,status,id_2,id_3,category_2 | category,parent_category | 4,4     | NULL                      | 67889 |     4.74 | Using union(category,parent_category); Using where |
|  1 | SIMPLE      | sc    | NULL       | eq_ref      | PRIMARY                                                                        | PRIMARY                  | 4       | abc_classified.p.category |     1 |   100.00 | NULL                                               |
|  1 | SIMPLE      | us    | NULL       | eq_ref      | PRIMARY                                                                        | PRIMARY                  | 4       | abc_classified.p.user_id  |     1 |   100.00 | NULL                                               |
|  1 | SIMPLE      | ht    | NULL       | ref         | ad_id                                                                          | ad_id                    | 4       | abc_classified.p.id       |     1 |   100.00 | NULL                                               |
+----+-------------+-------+------------+-------------+--------------------------------------------------------------------------------+--------------------------+---------+---------------------------+-------+----------+----------------------------------------------------+

我想我已经定义了适当的索引,有人能指出我做错了什么吗?或者如何减少执行时间?就我所知,为什么会发生这种情况?

当您在where条件中定义精确的值时,SQL使用
散列连接。因此,它比其他联接快得多。将其更改为非精确值条件(X或Y)时,速度会变慢


解决方案是建立一个
索引
,以减少要搜索的记录。

当您在where条件中定义精确值时,SQL使用
哈希联接
。因此,它比其他联接快得多。将其更改为非精确值条件(X或Y)时,速度会变慢


解决方法是建立一个
索引
,以减少要搜索的记录。

我认为您的查询将受益于联合而不是or。 这将创建两组数据。一个在类别ID上,另一个在父类别ID上。这比定义两个负集要快。一组不带categoryid=216,另一组不带父categoryid=216

SELECT DISTINCT p1.*,
        ht.html_title,
        ht.html_content,
        sc.sub_cat_name,
        sc.main_cat_id,
        us.username,
        c.name AS cityname
FROM   ad_product p1 inner join ad_html ht on ht.ad_id = p1.id
    inner join ad_category_sub sc on sc.sub_cat_id = p1.category
    inner join ad_user us on  us.id = p1.user_id 
    inner join ad_cities c on c.id = p1.city   
WHERE ( p1.status = 'active' )
   AND ( p1.city = 135 )
   AND ( p1.category = 216)
UNION
SELECT DISTINCT p.*,
        ht.html_title,
        ht.html_content,
        sc.sub_cat_name,
        sc.main_cat_id,
        us.username,
        c.name AS cityname
FROM   ad_product p 
    inner join ad_html ht on ht.ad_id = p.id
    inner join ad_category_sub sc on sc.sub_cat_id = p.category
    inner join ad_user us on us.id = p.user_id
    inner join ad_cities c on c.id = p.city
WHERE ( p.status = 'active' )
  AND ( p.city = 135 )
  AND (p.parent_category = 216)
ORDER  BY p.created_at DESC;

我认为你的问题将受益于工会而不是or。 这将创建两组数据。一个在类别ID上,另一个在父类别ID上。这比定义两个负集要快。一组不带categoryid=216,另一组不带父categoryid=216

SELECT DISTINCT p1.*,
        ht.html_title,
        ht.html_content,
        sc.sub_cat_name,
        sc.main_cat_id,
        us.username,
        c.name AS cityname
FROM   ad_product p1 inner join ad_html ht on ht.ad_id = p1.id
    inner join ad_category_sub sc on sc.sub_cat_id = p1.category
    inner join ad_user us on  us.id = p1.user_id 
    inner join ad_cities c on c.id = p1.city   
WHERE ( p1.status = 'active' )
   AND ( p1.city = 135 )
   AND ( p1.category = 216)
UNION
SELECT DISTINCT p.*,
        ht.html_title,
        ht.html_content,
        sc.sub_cat_name,
        sc.main_cat_id,
        us.username,
        c.name AS cityname
FROM   ad_product p 
    inner join ad_html ht on ht.ad_id = p.id
    inner join ad_category_sub sc on sc.sub_cat_id = p.category
    inner join ad_user us on us.id = p.user_id
    inner join ad_cities c on c.id = p.city
WHERE ( p.status = 'active' )
  AND ( p.city = 135 )
  AND (p.parent_category = 216)
ORDER  BY p.created_at DESC;

@Dwight Reynoldson Answers在SQL Server上运行得很好,我在MySQL上找到了一个解决“按订单”问题的方法。我所做的只是在DESC创建的订单而不是p创建的订单。在DESC创建的订单是p创建的

答复:

SELECT DISTINCT p1.*,
        ht.html_title,
        ht.html_content,
        sc.sub_cat_name,
        sc.main_cat_id,
        us.username,
        c.name AS cityname
FROM   ad_product p1 inner join ad_html ht on ht.ad_id = p1.id
    inner join ad_category_sub sc on sc.sub_cat_id = p1.category
    inner join ad_user us on  us.id = p1.user_id 
    inner join ad_cities c on c.id = p1.city   
WHERE ( p1.status = 'active' )
   AND ( p1.city = 135 )
   AND ( p1.category = 216)
UNION
SELECT DISTINCT p.*,
        ht.html_title,
        ht.html_content,
        sc.sub_cat_name,
        sc.main_cat_id,
        us.username,
        c.name AS cityname
FROM   ad_product p 
    inner join ad_html ht on ht.ad_id = p.id
    inner join ad_category_sub sc on sc.sub_cat_id = p.category
    inner join ad_user us on us.id = p.user_id
    inner join ad_cities c on c.id = p.city
WHERE ( p.status = 'active' )
  AND ( p.city = 135 )
  AND (p.parent_category = 216)
ORDER BY created_at DESC;

@Dwight Reynoldson Answers在SQL Server上运行得很好,我在MySQL上找到了一个解决“按订单”问题的方法。我所做的只是在DESC创建的订单而不是p创建的订单。在DESC创建的订单是p创建的

答复:

SELECT DISTINCT p1.*,
        ht.html_title,
        ht.html_content,
        sc.sub_cat_name,
        sc.main_cat_id,
        us.username,
        c.name AS cityname
FROM   ad_product p1 inner join ad_html ht on ht.ad_id = p1.id
    inner join ad_category_sub sc on sc.sub_cat_id = p1.category
    inner join ad_user us on  us.id = p1.user_id 
    inner join ad_cities c on c.id = p1.city   
WHERE ( p1.status = 'active' )
   AND ( p1.city = 135 )
   AND ( p1.category = 216)
UNION
SELECT DISTINCT p.*,
        ht.html_title,
        ht.html_content,
        sc.sub_cat_name,
        sc.main_cat_id,
        us.username,
        c.name AS cityname
FROM   ad_product p 
    inner join ad_html ht on ht.ad_id = p.id
    inner join ad_category_sub sc on sc.sub_cat_id = p.category
    inner join ad_user us on us.id = p.user_id
    inner join ad_cities c on c.id = p.city
WHERE ( p.status = 'active' )
  AND ( p.city = 135 )
  AND (p.parent_category = 216)
ORDER BY created_at DESC;

请将您的查询格式化为多行,以便我们可以读取它们。
union
解决方案应该有效,顺便说一句,您可以调用两个表
p
无需将顶部查询更改为p1。请将您的查询格式化为多行,以便我们可以读取它们。
union
解决方案应该有效,顺便说一句,您可以调用两个表
p
无需将顶部查询更改为p1。Reynoldson感谢您的回答。我试图执行查询,但出现了一个错误:“#1250-其中一个选择中的表'p'不能在字段列表中使用”我不明白它说了什么,可能您可以提供帮助!嗨,Aarav,我认为这个错误是由于在查询的上半部分和下半部分使用了相同的别名“p”造成的。我在代码示例中编辑了查询,以便在上半部分使用“p1”。试试看,让我知道你进展如何。如果仍然没有乐趣,我需要构建一个迷你版的数据结构来测试查询。你好,Reynoldson,谢谢你的编辑,但它给出了相同的错误“#1250-选择之一的表“p”不能在字段列表中使用”我甚至尝试将p更改为p2,但没有成功。你好,Aarav,我再次编辑了代码块。这对我来说并没有错误(我正在使用一个测试数据结构,它是用SQL server编写的,所以如果您使用的是mysql,可能需要翻译成mysql)。我基本上已经用连接替换了大多数where子句(优化器无论如何都会这样做),并且我仍然在利用联合来避免or运算符问题。我希望这能让你更接近。嘿,雷诺森,谢谢你的优化解决方案。它工作正常,但没有“订单依据”,因为它抛出了相同的“#1250”错误。在搜索了一段时间后,我发现当我们使用UNION或GROUP BY的“ORDER BY”时存在一些错误。我仍然在寻找ORDER BY的解决方案,但这样就可以了。非常感谢你的帮助!雷诺森:谢谢你的回答。我试图执行查询,但出现了一个错误:“#1250-其中一个选择中的表'p'不能在字段列表中使用”我不明白它说了什么,可能您可以提供帮助!嗨,Aarav,我认为这个错误是由于在查询的上半部分和下半部分使用了相同的别名“p”造成的。我在代码示例中编辑了查询,以便在上半部分使用“p1”。试试看,让我知道你进展如何。如果仍然没有乐趣,我需要构建一个迷你版的数据结构来测试查询。你好,Reynoldson,谢谢你的编辑,但它给出了相同的错误“#1250-选择之一的表“p”不能在字段列表中使用”我甚至尝试将p更改为p2,但没有成功。你好,Aarav,我再次编辑了代码块。这对我来说并没有错误(我正在使用一个测试数据结构,它是用SQL server编写的,所以如果您使用的是mysql,可能需要翻译成mysql)。我基本上已经用连接替换了大多数where子句(优化器无论如何都会这样做),并且我仍然在利用联合来避免or运算符问题。我希望这能让你更接近。嘿,雷诺森,谢谢你的优化解决方案。它工作正常,但没有“订单依据”,因为它抛出了相同的“#1250”错误。在搜索了一段时间后,我发现当我们使用UNION或GROUP BY的“ORDER BY”时存在一些错误。我仍然在寻找ORDER BY的解决方案,但这样就可以了。非常感谢你的帮助!我已经分别在“类别”和父类别上定义了索引。请看一看我发布的解释结果,它显示带有“或”的查询已经在使用索引。我已经分别在“类别”和父类别上定义了索引。请看一下我发布的解释结果,它显示带有“或”的查询已经在使用索引。