Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/55.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Database Mysql慢速查询:JOIN+;多个位置+;订购人_Database_Mysql_Indexing_Query Optimization - Fatal编程技术网

Database Mysql慢速查询:JOIN+;多个位置+;订购人

Database Mysql慢速查询:JOIN+;多个位置+;订购人,database,mysql,indexing,query-optimization,Database,Mysql,Indexing,Query Optimization,长时间潜伏者,第一个问题 我正在努力优化此查询,该查询选择与所选过滤器匹配的最低价项目: SELECT product_info.*, MIN(product_all.sale_price) as sale_price, product_all.buy_link FROM product_info NATURAL JOIN (SELECT * FROM product_all WHERE product_all.date = '2010-09-30') as product_all WHERE

长时间潜伏者,第一个问题

我正在努力优化此查询,该查询选择与所选过滤器匹配的最低价项目:

SELECT product_info.*, MIN(product_all.sale_price) as sale_price, product_all.buy_link
FROM product_info
NATURAL JOIN (SELECT * FROM product_all WHERE product_all.date = '2010-09-30') as product_all
WHERE (product_info.category = 2  
AND product_info.gender = 'W' )
GROUP BY product_all.prod_id
ORDER BY MIN(product_all.sale_price) ASC LIMIT 13
其解释是:

| id | select_type | table        | type   | possible_keys                                             | key     | key_len | ref                 | rows   | Extra                           |  
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+  
|  1 | PRIMARY     | <derived2>   | ALL    | NULL                                                     | NULL    | NULL    | NULL                | 89801  | Using temporary; Using filesort | 
|  1 | PRIMARY     | product_info | eq_ref | PRIMARY,category_prod_id_retail_price,category_ret...     | PRIMARY | 4       | product_all.prod_id | 1      | Using where                     | 
|  2 | DERIVED     | product_all  | ref    | date_2                                                    | date_2  | 3       |                     | 144107 |                                 | 
| id | select_type | table        | type | possible_keys                                             | key                      | key_len | ref                               | rows | Extra                                        |  
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+  
|  1 | SIMPLE      | product_info | ref  | PRIMARY,category_prod_id_retail_price,category_ret...     | category_retail_price    | 5       | const                             | 269  | Using where; Using temporary; Using filesort | 
|  1 | SIMPLE      | product_all  | ref  | PRIMARY,prod_id,date_2                                    | prod_id                  | 4       | equipster_db.product_info.prod_id | 141  | Using where                                  | 
及其解释:

| id | select_type | table        | type   | possible_keys                                             | key     | key_len | ref                 | rows   | Extra                           |  
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+  
|  1 | PRIMARY     | <derived2>   | ALL    | NULL                                                     | NULL    | NULL    | NULL                | 89801  | Using temporary; Using filesort | 
|  1 | PRIMARY     | product_info | eq_ref | PRIMARY,category_prod_id_retail_price,category_ret...     | PRIMARY | 4       | product_all.prod_id | 1      | Using where                     | 
|  2 | DERIVED     | product_all  | ref    | date_2                                                    | date_2  | 3       |                     | 144107 |                                 | 
| id | select_type | table        | type | possible_keys                                             | key                      | key_len | ref                               | rows | Extra                                        |  
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+  
|  1 | SIMPLE      | product_info | ref  | PRIMARY,category_prod_id_retail_price,category_ret...     | category_retail_price    | 5       | const                             | 269  | Using where; Using temporary; Using filesort | 
|  1 | SIMPLE      | product_all  | ref  | PRIMARY,prod_id,date_2                                    | prod_id                  | 4       | equipster_db.product_info.prod_id | 141  | Using where                                  | 
以下是表格:

CREATE TABLE `product_all` (
`prod_id` INT( 10 ) NOT NULL PRIMARY KEY ,
`ref_id` INT( 10) NOT NULL PRIMARY KEY ,
`date` DATE NOT NULL ,
`buy_link` BLOB NOT NULL ,
`sale_price` FLOAT NOT NULL
) ENGINE = MYISAM ;


CREATE TABLE `product_info` (
`prod_id` INT( 10 ) NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`prod_name` VARCHAR( 200 ) NOT NULL,
`brand` VARCHAR( 50 ) NOT NULL,
`retail_price` FLOAT NOT NULL
`category` INT( 3 ) NOT NULL,
`gender` VARCHAR( 1 ) NOT NULL,
`type` VARCHAR( 10 ) NOT NULL
) ENGINE = MYISAM ;
我的问题:
-哪种查询结构似乎是最佳的?
-哪些索引将优化此查询?
-不太重要的是:当添加或删除WHERE子句或使用不同的排序方式(如按%off排序)时,索引方法如何改变:

ORDER BY (1-(MIN(product_all.sale_price)/product_info.retail_price)) DESC  

编辑:两个查询的自然连接作用于prod\u id(product\u info中的一条记录可以在product\u all中有多个实例,这就是它们需要分组的原因)

索引在mysql中起着巨大的作用,一个查询用了15分钟的时间,而一组错误的索引用了2秒,但找到正确的平衡通常是问题所在。当然,如果没有一些示例数据,很难说下面的解决方案是否能为您节省时间,但理论上应该如此

为了回答您的问题,我将重新设计表格,如下所示:

CREATE TABLE `product_all` ( 
`prod_id` INT( 10 ) NOT NULL, 
`ref_id` INT( 10) NOT NULL, 
`date` DATE NOT NULL , 
`buy_link` BLOB NOT NULL , 
`sale_price` FLOAT NOT NULL,
PRIMARY KEY (prod_id, ref_id) ,
INDEX date_Index (`date` ASC),
UNIQUE INDEX prod_price_Index (prod_id ASC, sale_price ASC)
) ENGINE = MYISAM ; 


CREATE TABLE `product_info` ( 
`prod_id` INT( 10 ) NOT NULL AUTO_INCREMENT, 
`prod_name` VARCHAR( 200 ) NOT NULL, 
`brand` VARCHAR( 50 ) NOT NULL, 
`retail_price` FLOAT NOT NULL, 
`category` INT( 3 ) NOT NULL, 
`gender` VARCHAR( 1 ) NOT NULL, 
`type` VARCHAR( 10 ) NOT NULL,
PRIMARY KEY (prod_id) ,
UNIQUE INDEX prod_id_name_Index (prod_id ASC, prod_name ASC),
INDEX category_Index (category ASC),
INDEX gender_Index (gender ASC)
) ENGINE = MYISAM ;

SELECT product_info.*, MIN(product_all.sale_price) as sale_price, product_all.buy_link         
FROM product_info         
NATURAL JOIN (SELECT * FROM product_all WHERE product_all.date = '2010-09-30') as product_all         
WHERE (product_info.category = 2           
AND product_info.gender = 'W' )         
GROUP BY product_all.prod_id         
ORDER BY MIN(product_all.sale_price) ASC LIMIT 13        
这里的性能增益是通过索引where子句中加入的主要字段而获得的。就个人而言,我会同意你的第一个问题,因为当你考虑它时,它应该表现得更好

据我所知,在第一个和第二个查询中发生了什么:

  • 第一个查询正在被筛选 执行以下操作之前的子查询: 自然连接,这意味着它只有 加入结果数据,而不是 整张桌子
  • 第二个查询是加入 整个第二张桌子,然后 筛选 一切都回到你想要的
根据经验,通常您希望在主要连接字段上添加索引,也希望在where子句中使用最多的字段上添加索引。我还将一些独特的索引放在一些您希望定期查询的字段上,例如prod\u id\u name\u Index

如果这不能提高您的性能,如果您可以发布一些虚拟数据来使用,我可能可以得到一个更快的解决方案,我可以对其进行基准测试

这是一篇介绍mysql性能索引的文章,如果您想了解更多,值得一读

祝你好运


编辑:我第一次错过了你的最后一个问题,答案是,如果你对主要连接字段进行索引,那么对where的更改只会对整体性能产生轻微影响,但是我在表上放置的唯一索引应该是你希望查询所基于的大部分内容。要记住的主要一点是,如果您经常查询或连接某个字段,那么它确实应该被索引,但是您不必担心在重新调整索引策略方面的小查询和对顺序的更改。

就性能而言,使用它从来都不是一件好事

select *
您应该改用单独的列名

select column1,column2 etc...

就我个人而言,我是一个sql极简主义者,避免任何不能索引到索引列的子查询或联接

如果这真的不可能,我可能会单独运行子查询来收集密钥,在客户端站点对它们进行排序,然后构建where in(…)子句

JohnVD提出了很多好的观点,但如果您需要制作一个包含产品名称的唯一键,那么您应该真正了解它是否可以规范化为一个it

如果可能的话,要不惜一切代价避免索引varchar列。每个索引项都与列的最大大小一样大,即使它们通常只是列的一小部分。如果使用utf-8这样的字符集,那么大小是~maxlen+3


由于你方的限制,似乎需要订货。但是,作为一个参考,当你做分组时,如果你要使用整个结果集,那么就加上一个空的订单。通过explain运行这两个变体,了解原因;ORDERBYNULL消除了隐含的filesort,您可以在客户端对其进行排序。(如果您使用rollup执行group by,这是不可能的)

您应该坚持第二个查询。对列使用索引,以最大程度地减少受影响的行。在这种情况下,可能是日期。如果筛选条件始终包含多个列,则应尝试使用多列索引。MySQL将只使用一个索引。

正如米奇所说,试图找到自然具有较低记录数的标准肯定会赢得性能。如果Category+Gender非常常见,那么将其作为两列的索引。此外,一旦找到了最佳条件,您可以修改以下查询以更好地匹配它。“STRAIGHT_JOIN”告诉MySQL按照您声明的顺序进行操作,而不是试图更改用于查询basis和连接到其他数据库的主表。。。所以,我不知道哪一个更准确的分类索引、性别索引或日期索引。。。如果Date的记录基础更少,那么我会将其作为FROM子句中的第一个表进行交换,并在心里将其关于Date的标准移动到WHERE子句的第一个位置(只有我个人才能在视觉上与表保持同步)。我已经看到,在许多看似简单的查询的情况下,STRAIGHT_JOIN显著提高了性能

SELECT STRAIGHT_JOIN
      product_info.*, 
      MIN(product_all.sale_price) as sale_price, 
      product_all.buy_link 
   FROM 
      product_info,
      product_all 
   where 
          product_info.category = 2   
      AND product_info.gender = 'W'
      and product_info.prod_id = product_all.prod_id
      AND product_all.date = '2010-09-30'
   GROUP BY 
      product_info.prod_id 
   ORDER BY 
      MIN(product_all.sale_price) ASC 
   LIMIT 13 

其中一个PK是复合的,但每个组是一行:产品ID、该产品的最低价格和相关数据。编辑:这是对一条似乎已经消失的评论的回应。编辑2:是的,我想我点击了编辑而不是添加评论…很流畅。这是我知道的为数不多的事情之一,但我认为这可以忽略不计,并且可以提高我问题的可读性。乔恩,谢谢!这些多列索引起到了作用,而且您的编辑也很准确,order by并没有真正地向下拖动查询,因为它只对13行进行操作。干杯乔恩,你帮了我们大忙。上面的那个