【问题标题】:Where to start with optimizing/adding indexes to speed up query?从哪里开始优化/添加索引以加快查询速度?
【发布时间】:2011-11-16 09:28:47
【问题描述】:

我不确定从哪里开始在我网站的搜索部分减少此查询,以免花费很长时间。您在各种表格上运行搜索,并主要从“项目”表格中获取过滤结果,目前它(和类似的搜索)有时需要超过 10 秒。部分问题是组成 sql 的 php 代码当然是脏得要命,而且我不习惯通常需要优化的大量查询,但是我可以使用哪些技术来确定在哪里添加像这样的查询中的索引?

查询

SELECT
    items.ItemId,
    items.Name,
    items.BrandCode,
    items.BrandCategoryId,
    items.CatalogPage,
    items.PriceRetail,
    items.PriceSell,
    items.PriceHold,
    items.Descr,
    items.GenderId,
    products.ImagetnURL,
    products.FlagDefault,
    products.ProductId,
    products.Code AS ProductCode,
    products.Name AS ProductName,
    brands.Name AS BrandName,
    items.FlagStatus AS ItemFlagStatus
FROM
    items,
    products,
    brands,
    productsizes,
    searchsizechartsizes,
    sizechartsizes
WHERE
    items.ItemId = products.ItemId AND
    items.BrandCode = brands.Code AND
    items.FlagStatus != 'U' AND
    products.FlagStatus != 'U' AND
    items.TypeId = '10' AND
    searchsizechartsizes.SearchSizeChartId = '11' AND
    searchsizechartsizes.Size = sizechartsizes.Size AND
    sizechartsizes.SizeChartId = productsizes.SizeChartId AND
    productsizes.ProductId = products.ProductId
GROUP BY
    items.ItemId
ORDER BY
    items.Name
LIMIT
    0, 15;

日志显示执行时间为 14 秒,检查了 300 万行

# Query_time: 14  Lock_time: 0  Rows_sent: 15  Rows_examined: 2901565

查询结果汇总

+--------+----------------------+-----------+-----------------+-------------+-------------+-----------+-----------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------+----------------------------+-------------+-----------+-------------+------------------------------------------+-------------------+----------------+
| ItemId | Name                 | BrandCode | BrandCategoryId | CatalogPage | PriceRetail | PriceSell | PriceHold | Descr | GenderId | ImagetnURL  | FlagDefault | ProductId | ProductCode | ProductName | BrandName         | ItemFlagStatus |
+--------+----------------------+-----------+-----------------+-------------+-------------+-
|   3376 | 10-inch Pull On Boot | RW        |            2801 |          24 |      189.99 |    189.99 |    189.99 | Full grain brown leather - blah blah blah |        1 | images/rw/rw-2249tn.jpg    | Y           |      4345 | 2249        | Brown Full Grain Turbo Vegas Leather                    | Red Wing Work     | A              | 
|   9340 | 11                   | RR        |            NULL |           1 |      300.00 |    300.00 |    300.00 | The Engineer 11" boot from Red Wing Shoes�  blah blah blah... |        1 | images/rr/rr-2990tn.jpg    | Y           |     16749 | 2990        | Black Harness Calfskin                                  | Red Wing Heritage | A              
~~~~~~ other results here redacted for space reasons ~~~~~~
15 rows in set (13.33 sec)

查询说明

mysql> explain SELECT items.ItemId, items.Name, items.BrandCode, items.BrandCategoryId, items.CatalogPage, items.PriceRetail, items.PriceSell, items.PriceHold, items.Descr, items.GenderId, products.ImagetnURL, products.FlagDefault,  products.ProductId, products.Code as ProductCode, products.Name as ProductName, brands.Name as BrandName, items.FlagStatus as ItemFlagStatus  FROM items, products, brands, productsizes, searchsizechartsizes, sizechartsizes  WHERE items.ItemId = products.ItemId AND items.BrandCode = brands.Code AND items.FlagStatus != 'U' AND products.FlagStatus != 'U' AND items.TypeId = '10' AND (searchsizechartsizes.SearchSizeChartId = '11' AND searchsizechartsizes.Size = sizechartsizes.Size AND sizechartsizes.SizeChartId = productsizes.SizeChartId AND productsizes.ProductId = products.ProductId)   group by items.ItemId  ORDER BY items.Name LIMIT 0, 15;
+----+-------------+----------------------+--------+------------------------------------------------+-------------+---------+----------------------------------------+------+---------------------------------+
| id | select_type | table                | type   | possible_keys                                  | key         | key_len | ref                                    | rows | Extra                           |
+----+-------------+----------------------+--------+------------------------------------------------+-------------+---------+----------------------------------------+------+---------------------------------+
|  1 | SIMPLE      | searchsizechartsizes | ref    | PRIMARY,Size                                   | PRIMARY     | 4       | const                                  |    2 | Using temporary; Using filesort | 
|  1 | SIMPLE      | brands               | ALL    | NULL                                           | NULL        | NULL    | NULL                                   |   40 |                                 | 
|  1 | SIMPLE      | sizechartsizes       | ref    | Size,SizeChartId                               | Size        | 33      | shermanbros.searchsizechartsizes.Size  |  217 | Using where                     | 
|  1 | SIMPLE      | productsizes         | ref    | ProductId,SizeChartId                          | SizeChartId | 5       | shermanbros.sizechartsizes.SizeChartId |   17 | Using where                     | 
|  1 | SIMPLE      | products             | eq_ref | PRIMARY,FlagStatus,flagstatusanddefault,ItemId | PRIMARY     | 4       | shermanbros.productsizes.ProductId     |    1 | Using where                     | 
|  1 | SIMPLE      | items                | eq_ref | PRIMARY,BrandCode,TypeId,FlagStatus,ItemsIndex | PRIMARY     | 4       | shermanbros.products.ItemId            |    1 | Using where                     | 
+----+-------------+----------------------+--------+------------------------------------------------+-------------+---------+----------------------------------------+------+---------------------------------+
6 rows in set (0.02 sec)

项目表的结构

mysql> show create table items;
+-------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
+-------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| items | CREATE TABLE `items` (
  `ItemId` int(11) NOT NULL auto_increment,
  `Code` varchar(25) default NULL,
  `Name` varchar(100) default NULL,
  `BrandCode` char(2) default NULL,
  `CatalogPage` int(3) default NULL,
  `BrandCategoryId` int(11) default NULL,
  `TypeId` int(11) default NULL,
  `StyleId` int(11) default NULL,
  `GenderId` int(11) default NULL,
  `PriceRetail` decimal(6,2) default NULL,
  `PriceSell` decimal(6,2) default NULL,
  `PriceHold` decimal(6,2) default NULL,
  `Cost` decimal(6,2) default NULL,
  `PriceNote` longtext,
  `FlagTaxable` char(1) default NULL,
  `FlagStatus` char(1) default NULL,
  `FlagFeatured` char(1) default NULL,
  `MaintFlagStatus` char(1) default NULL,
  `Descr` longtext,
  `DescrNote` longtext,
  `ImagetnURL` varchar(50) default NULL,
  `ImagefsURL` varchar(50) default NULL,
  `ImagelsURL` varchar(50) default NULL,
  `DateCreated` date NOT NULL default '0000-00-00',
  `DateStatus` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
  `AdminNote` text,
  PRIMARY KEY  (`ItemId`),
  KEY `BrandCode` (`BrandCode`),
  KEY `Name` (`Name`),
  KEY `TypeId` (`TypeId`),
  KEY `StyleId` (`StyleId`),
  KEY `GenderId` (`GenderId`),
  KEY `FlagStatus` (`FlagStatus`),
  KEY `ItemsIndex` (`TypeId`,`FlagStatus`,`ItemId`)
) ENGINE=MyISAM AUTO_INCREMENT=10216 DEFAULT CHARSET=latin1 | 
+-------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

items 表上的现有索引

mysql> show indexes from items;
+-------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| Table | Non_unique | Key_name   | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+-------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| items |          0 | PRIMARY    |            1 | ItemId      | A         |        8678 |     NULL | NULL   |      | BTREE      |         | 
| items |          1 | BrandCode  |            1 | BrandCode   | A         |          36 |     NULL | NULL   | YES  | BTREE      |         | 
| items |          1 | Name       |            1 | Name        | A         |        8678 |     NULL | NULL   | YES  | BTREE      |         | 
| items |          1 | TypeId     |            1 | TypeId      | A         |          17 |     NULL | NULL   | YES  | BTREE      |         | 
|     items |          1 | StyleId    |            1 | StyleId     | A         |          41 |     NULL | NULL   | YES  | BTREE      |         | 
| items |          1 | GenderId   |            1 | GenderId    | A         |           3 |     NULL | NULL   | YES  | BTREE      |         | 
| items |          1 | FlagStatus |            1 | FlagStatus  | A         |           6 |     NULL | NULL   | YES  | BTREE      |         | 
| items |          1 | ItemsIndex |            1 | TypeId      | A         |          17 |     NULL | NULL   | YES  | BTREE      |         | 
| items |          1 | ItemsIndex |            2 | FlagStatus  | A         |          52 |     NULL | NULL   | YES  | BTREE      |         | 
| items |          1 | ItemsIndex |            3 | ItemId      | A         |        8678 |     NULL | NULL   |      | BTREE      |         | 
+-------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
10 rows in set (0.00 sec)

它似乎已经在各个列上建立了索引,但是这些索引对于这个搜索查询来说仍然很慢。还有一个关于 typeid、flagstats、itemid 的多索引,用于优化单独的查询。

是的,如您所见,items 表本身就是一头野兽,这可能无济于事。

【问题讨论】:

  • 第一条评论:查询中的 GROUP BY 子句没有意义,你没有使用任何聚合函数。它应该被删除。

标签: mysql search optimization indexing


【解决方案1】:

查看您的 FROM 和 WHERE 子句:

FROM
    items,
    products,
    brands,
    productsizes,
    searchsizechartsizes,
    sizechartsizes
WHERE
    items.ItemId = products.ItemId AND
    items.BrandCode = brands.Code AND
    items.FlagStatus != 'U' AND
    products.FlagStatus != 'U' AND
    items.TypeId = '10' AND
    searchsizechartsizes.SearchSizeChartId = '11' AND
    searchsizechartsizes.Size = sizechartsizes.Size AND
    sizechartsizes.SizeChartId = productsizes.SizeChartId AND
    productsizes.ProductId = products.ProductId

您已将所有连接逻辑放入 WHERE 子句中,这在阅读查询时没有帮助。改用显式连接语法,我们可以改写如下:

FROM
    items
    JOIN products ON items.ItemId = products.ItemId
    JOIN brands ON items.BrandCode = brands.Code
    JOIN productsizes ON products.ProductId = productsizes.ProductId
    JOIN sizechartsizes ON sizechartsizes.SizeChartId = productsizes.SizeChartId
    JOIN searchsizechartsizes ON sizechartsizes.Size = searchsizechartsizes.Size
WHERE
    items.FlagStatus != 'U' AND
    items.TypeId = '10' AND
    products.FlagStatus != 'U' AND
    searchsizechartsizes.SearchSizeChartId = '11'

这样可以更清楚地知道发生了什么。

似乎您在 ItemsIndex 中有一个很好的候选索引。 (顺便说一句,TypeID 上的索引是多余的,应该删除,因为 TypeID 是 ItemsIndex 的左前缀。)不幸的是,MySQL 的查询优化器似乎认为从后到前进行连接更有意义,从表搜索大小图表大小。我不确定它为什么会这样做,但我注意到表品牌显然没有定义可用的键。对此进行调查可能是个好主意。

【讨论】:

  • 是的,这很多都是以前的开发人员的工作。我计划尽可能将连接重写为显式,它们是 sql 在代码中连接在一起的方式的症状(例如,如果添加了另一个搜索条件,则添加另一个表,有条件地添加到 from 列表和where 子句。)不幸的是,php 代码非常丑陋,所以我需要一段时间才能完全重写其中的那些部分。
  • 类似地,原版中的 group by 是为了防止在某些代码块发挥作用时出现重复(替换之前存在的 select distinct)。 Brands 通过文本代码加入(例如“RW”或“CH”,而不是 id,尽管表本身确实有有效的 id)。我认为这往往会导致问题?如果当前的“ItemsIndex”是一个不错的候选者,那么问题可能出在非显式连接上,我将根据您的建议修改运行一些选择,看看会发生什么。
  • 带有显式连接的选择似乎给出了几乎相同的时间结果(13 秒),但删除组(当然,当我可以时)将查询速度加快到 1 秒以下,所以我'将首先考虑处理!
猜你喜欢
  • 2023-01-05
  • 2023-03-15
  • 1970-01-01
  • 1970-01-01
  • 2018-11-30
  • 2022-09-28
  • 1970-01-01
  • 2011-05-09
  • 1970-01-01
相关资源
最近更新 更多