1

我有一个非常庞大的查询要优化,它由 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) OR p.category IN ( 99, 1 , 5, 8458, ...))

查询如下所示:

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

谢谢

更新!!!!

我注意到为什么查询如此缓慢我创建的新列,使用 IF 语句oPrices然后使用“ORDER BY oPricesDESC”使查询变慢,一旦我删除它,查询只需要 0.00009 秒,这太棒了! !但是现在我不会得到正确排序的数据,即使我用 PHP 进行排序,我也必须创建一个不理想的新分页函数。

4

1 回答 1

2

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

从这个链接:

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

我们看到,对于大型参数列表,将它们传递到临时表中比作为常量列表要快得多,而对于小型列表,性能几乎相同。

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

于 2012-09-19T15:58:54.613 回答