MySQL查询在大数据上的速度非常慢

MySQL查询在大数据上的速度非常慢,mysql,pdo,Mysql,Pdo,我不是MySQL高手,但我明白了,我刚刚继承了一个相当大的表(600000行和大约90列(请杀了我…),我创建了一个较小的表,将它与一个categories表链接起来 我试图用一个左连接查询所说的表,所以我在一个对象中有两组数据,但它运行得非常慢,我没有足够的热量来排序它;我真的很想得到一些指导和解释,解释一下为什么它这么慢 SELECT `products`.`Product_number`, `products`.`Price`, `products`.`Previ

我不是MySQL高手,但我明白了,我刚刚继承了一个相当大的表(600000行和大约90列(请杀了我…),我创建了一个较小的表,将它与一个categories表链接起来

我试图用一个左连接查询所说的表,所以我在一个对象中有两组数据,但它运行得非常慢,我没有足够的热量来排序它;我真的很想得到一些指导和解释,解释一下为什么它这么慢

SELECT 
    `products`.`Product_number`,
    `products`.`Price`,
    `products`.`Previous_Price_1`,
    `products`.`Previous_Price_2`,
    `products`.`Product_number`,
    `products`.`AverageOverallRating`,
    `products`.`Name`,
    `products`.`Brand_description`
FROM `product_categories`
LEFT OUTER JOIN `products`
ON `products`.`product_id`= `product_categories`.`product_id`
WHERE COALESCE(product_categories.cat4, product_categories.cat3,
product_categories.cat2, product_categories.cat1) = '123456'
AND `product_categories`.`product_id` != 0
这两个表是MyISAM,products表对Product_number和Brand_Description进行了索引,Product_categories表对组合的所有列进行了唯一索引;如果这个信息有任何帮助

继承了这个系统之后,我需要在我使用核武器之前尽快让它工作起来,并正确地使用它,所以现在的任何帮助都将赢得我最大的尊重

[编辑] 以下是explain extended的输出:

+----+-------------+--------------------+-------+---------------+------+---------+------+---------+----------+--------------------------+
| id | select_type | table              | type  | possible_keys | key  | key_len | ref  | rows    | filtered | Extra                    |
+----+-------------+--------------------+-------+---------------+------+---------+------+---------+----------+--------------------------+
|  1 | SIMPLE      | product_categories | index | NULL          | cat1 | 23      | NULL | 1224419 |   100.00 | Using where; Using index |
|  1 | SIMPLE      | products           | ALL   | Product_id    | NULL | NULL    | NULL |  512376 |   100.00 |                          |
+----+-------------+--------------------+-------+---------------+------+---------+------+---------+----------+--------------------------+
优化表 为了建立一个基线,我首先建议在两个表上运行一个命令。请注意,这可能需要一些时间。从:

如果删除了一个表的大部分,则应使用
优化表
表,或者如果您对具有可变长度的表进行了多次更改 行(具有
VARCHAR、VARBINARY、BLOB
TEXT
列的表)。 已删除的行保存在链表中,后续的
INSERT
操作重用旧的行位置。您可以使用
优化表
来 回收未使用的空间并对数据文件进行碎片整理。之后 对表进行大量更改,此语句也可能会有所改进 使用表格的语句的性能,有时非常重要。

[……]

对于MyISAM表,
优化表
的工作原理如下:

  • 如果该表已删除或拆分行,请修复该表

  • 如果索引页未排序,请对其进行排序

  • 如果表的统计信息不是最新的(并且无法通过对索引排序来完成修复),请更新它们

  • 索引 如果不关心空间和索引管理,可以尝试在

    如果在查询中经常使用这些列中最左边的子集,则建议这样做。查询计划表明它可以使用
    产品类别
    cat1
    索引。这很可能只包括
    cat1
    列。通过将所有四个类别列添加到索引中,它可以更有效地查找所需的行。从:

    MySQL可以使用多个列索引进行查询,以测试所有 索引中的列,或仅测试第一列的查询 前两列、前三列,依此类推。如果您指定 索引定义中顺序正确的列,单个 复合索引可以加速对同一数据库的多种查询 桌子

    结构 此外,考虑到您的表有90列,您还应该意识到这一点。您可能需要将表考虑到多个表:

    列太多可能会使记录的大小膨胀,从而 导致更多内存块被读入和读出内存,从而导致 较高的I/O。这可能会影响性能。解决这个问题的一个办法是 将表拆分为更小、更独立的表,并使用更小的 基数大于原始基数。现在,这应该允许更好的解决方案 阻塞因子(如上定义),这意味着更少的I/O和更快的速度 性能。像这样把桌子拆开的过程是一个复杂的过程 称为垂直分区

    优化表 为了建立一个基线,我首先建议在两个表上运行一个命令。请注意,这可能需要一些时间。从:

    如果删除了一个表的大部分,则应使用
    优化表
    表,或者如果您对具有可变长度的表进行了多次更改 行(具有
    VARCHAR、VARBINARY、BLOB
    TEXT
    列的表)。 已删除的行保存在链表中,后续的
    INSERT
    操作重用旧的行位置。您可以使用
    优化表
    来 回收未使用的空间并对数据文件进行碎片整理。之后 对表进行大量更改,此语句也可能会有所改进 使用表格的语句的性能,有时非常重要。

    [……]

    对于MyISAM表,
    优化表
    的工作原理如下:

  • 如果该表已删除或拆分行,请修复该表

  • 如果索引页未排序,请对其进行排序

  • 如果表的统计信息不是最新的(并且无法通过对索引排序来完成修复),请更新它们

  • 索引 如果不关心空间和索引管理,可以尝试在

    如果在查询中经常使用这些列中最左边的子集,则建议这样做。查询计划表明它可以使用
    产品类别
    cat1
    索引。这很可能只包括
    cat1
    列。通过将所有四个类别列添加到索引中,它可以更有效地查找所需的行。从:

    MySQL可以使用多个列索引进行查询,以测试所有 索引中的列,或仅测试第一列的查询 前两列、前三列,依此类推。如果您指定 索引定义中顺序正确的列,单个 复合索引可以加速对同一数据库的多种查询 桌子

    结构 此外,考虑到您的表有90列,您还应该意识到这一点。您可能需要将表考虑到多个表:

    列太多会导致记录大小膨胀,我认为
    product_categories.cat4, product_categories.cat3, product_categories.cat2, product_categories.cat1
    
    FROM `product_categories` pc 
    LEFT OUTER JOIN `products` p ON p.category_id = pc.id
    WHERE 
        COALESCE(product_categories.cat4, product_categories.cat3,product_categories.cat2, product_categories.cat1) = '123456'
        AND pc.id != 0
    
    SELECT  /* some columns from the products table */
      FROM products
     WHERE product_id IN 
     (
         SELECT DISTINCT product_id 
                    FROM product_categories
                   WHERE product_id <> 0
                     AND (   cat1='123456'
                          OR cat2='123456'
                          OR cat3='123456'
                          OR cat4='123456')
     )
    
    SELECT  /* some columns from the products table */
      FROM products
     WHERE product_id IN 
     (
         SELECT product_id 
           FROM product_categories
          WHERE MATCH(cat1,cat2,cat3,cat4) 
                AGAINST('123456' IN BOOLEAN MODE)
            AND product_id <> 0
    
     )
    
     CREATE FULLTEXT INDEX cat_lookup 
                        ON product_categories (cat1, cat2, cat3, cat4)
    
        cat1     cat2     cat3     cat4   
      123451   123453   123455   123456      matches your and my queries
      123456   123455   123454   123452      matches my queries but not yours