使用大量IN条目优化查询

时间:2012-09-19 15:56:25

标签: mysql mysqli

我有一个我想要优化的大量查询,它包含1个表请求和5个表左连接。 此查询需要0.3428秒才能完成(结果:总计4,340,查询耗时0.3428秒) 我正在处理大约10000个肯定会增长的条目。

现在查询它本身不是问题,它是IN语句中最大的问题。

  1. 我有2个IN语句
  2. 两者都在WHERE声明中
  3. 对于此特定页面加载,两者都有大量ID,3344个id条目数例如:(99,1,5,8458,...)
  4. 两个IN语句将具有相同的3344 ID的示例:((cf.catid IN(99,1,5,8458,...)AND cf.cid = c.id)或p.category IN( 99,1,5,8458,......))
  5. 查询如下所示:

    SELECT 
        p.id, c.id AS pCid, c.name AS cName, p.name, p.seo, 
        p.description AS pDescription, cd.description,
        p.category, p.archive, cf.catid, cf.pid, p.order_nr, 
        c.order_nr AS cOrder, c.seo AS cSeo, cat.name AS catName, 
        cat.order_id, pr.price, pr.sale_price, pr.sale_expiry,
        IF( pr.sale_price > 0, pr.sale_price, pr.price ) AS `oPrices`,
        pr.member_price, p.`set`, p.get_the_look,
        c.from_text_price, c.thumb, c.code AS colour_code, 
        p.code AS product_code, p.supplier_part_number, 
        p.oem_part_number, p.make, p.model, p.year, p.sub_model
    FROM 
        products p
        LEFT JOIN category_featured cf ON p.id=cf.pid
        LEFT JOIN colours c ON c.pid=p.id
        LEFT JOIN colour_descriptions cd ON c.id=cd.colour_id
        LEFT JOIN category cat ON cat.id=p.category
        LEFT JOIN pricing pr ON pr.cid=c.id
    WHERE 
        (
            (cf.catid IN ( .. 3344 ID entries .. ) AND cf.cid=c.id) OR p.category IN ( .. 3344 ID entries .. )
        )
        AND p.archive='0'
    
        AND p.status='1' AND c.status='1' 
        AND c.archive='0'
        AND cat.status IN (1,2)
    
    GROUP BY `c`.`id`
    ORDER BY `oPrices` DESC
    

    是否有更好的方法使用IN语句检查表中的特定ID,或者可以一起使用不同的检查?

    速度是这里的主要问题,我希望尽可能达到最佳性能。

    到目前为止我做了什么,以及如何设置一些设置:

    • 我为这些表创建了索引(只有在此查询中使用的INT(整数)列具有索引)
    • 有些表是MyISAM,有些是InnoDB(查询中未使用的其他表与查询中的几个表有关系,所以它们必须是InnoDB)
    • 查询中的表之间没有关系
    • 运行查询我使用PHP和MySQLI

    由于

    UPDATE !!!!

    我注意到为什么我创建的新列的查询速度太慢,使用IF语句oPrices然后使用“ORDER BY oPrices DESC”使查询变慢,一旦我删除它查询只需要0.00009秒,这是惊人的!但是现在我不会得到正确排序的数据,如果我用PHP进行排序,我将不得不创建一个不理想的新分页功能。

1 个答案:

答案 0 :(得分:2)

IN可能会使查询非常难以优化,因为可能未被使用(您可以使用EXPLAIN验证这一点)。另一种方法是将这些ID加载到临时表中,然后执行JOIN

从这个链接:

http://explainextended.com/2009/08/18/passing-parameters-in-mysql-in-list-vs-temporary-table/

  

我们看到对于大量参数列表,将它们传递给   临时表比常量列表快得多,而对于   小名单的表现几乎是一样的。

     

使用临时表是传递大型数组的最佳方法   MySQL中的参数。