我遇到一些问题,一些mysql查询需要大约50秒执行一些时间,但有时候大约1秒钟。查询做了我需要做的事情,但显然太慢了。
以下是使用的三个表并显示了一些列:
产品表(14315行)
id | title | image | price | rrp | upsell
20381 | test | test | 24.00 | 30.00 | 1
product_to_category表(26283行)
ptc_id | product_id | category_id
33797 | 20381 | 29
category_description表(29行)
category_id | name | url_slug
29 | Kitchens | kitchen-products
seo_slugs表(14898行)
seo_slug_id | route | seo_slug
26987 | product=20381 | test-product-kitchen-area-2000-500
以下是我正在使用的当前codeigniter函数。
public function getUpsells() {
$this->db->select('products.id, products.title, products.image, products.category, products.price, products.rrp', FALSE);
$this->db->from('product_to_category');
$this->db->join('products', 'products.id = product_to_category.product_id');
$this->db->join('category_description', 'category_description.category_id = product_to_category.category_id');
$this->db->join('seo_slugs', 'seo_slugs.route = concat(\'product=\', product_to_category.product_id)');
$this->db->where('products.upsell',1);
$this->db->where('products.status',1);
$this->db->group_by('product_to_category.product_id');
$query = $this->db->get();
return $query->result();
} 我希望有人可以指出我正确的方向,并告诉我哪里出错了。说实话,我第一次在查询中使用了连接,虽然它似乎有用,但是在第一次加载页面时通常很慢,如果刷新等,它似乎加载相当快。
以下是它运行的查询:
SELECT products.id, products.title, products.image, products.category, products.price, products.rrp
FROM `product_to_category`
JOIN `products` ON `products`.`id` = `product_to_category`.`product_id`
JOIN `category_description` ON `category_description`.`category_id` = `product_to_category`.`category_id`
JOIN `seo_slugs` ON `seo_slugs`.`route` = concat('product=', product_to_category.product_id)
WHERE `products`.`upsell` = 1
AND `products`.`status` = 1
GROUP BY `product_to_category`.`product_id`
分析结果:
Starting 18 µs
Waiting For Query Cache Lock 5 µs
Checking Query Cache For Query 48 µs
Checking Permissions 5 µs
Checking Permissions 4 µs
Checking Permissions 4 µs
Checking Permissions 5 µs
Opening Tables 20 µs
System Lock 9 µs
Waiting For Query Cache Lock 15 µs
Init 25 µs
Optimizing 13 µs
Statistics 23 µs
Preparing 19 µs
Creating Tmp Table 21 µs
Executing 5 µs
Copying To Tmp Table 51.8 s
Sorting Result 26 µs
Sending Data 24 µs
End 9 µs
Removing Tmp Table 33 µs
End 7 µs
Query End 7 µs
Closing Tables 14 µs
Freeing Items 12 µs
Waiting For Query Cache Lock 6 µs
Freeing Items 11 µs
Waiting For Query Cache Lock 7 µs
Freeing Items 7 µs
Storing Result In Query Cache 162 µs
Logging Slow Query 6 µs
Logging Slow Query 38 µs
Cleaning Up 7 µs
EXPLAIN结果:
+----+-------------+----------------------+--------+---------------+---------+---------+-----------------------------------------------------+-------+---------------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+----------------------+--------+---------------+---------+---------+-----------------------------------------------------+-------+---------------------------------+ | 1 | SIMPLE | seo_slugs | ALL | NULL | NULL | NULL | NULL | 14958 | Using temporary; Using filesort | | 1 | SIMPLE | product_to_category | ALL | category_id | NULL | NULL | NULL | 26343 | Using where; Using join buffer | | 1 | SIMPLE | category_description | eq_ref | PRIMARY | PRIMARY | 4 | wilsonar_hcsupplies.product_to_category.category_id | 1 | Using index | | 1 | SIMPLE | products | eq_ref | PRIMARY,id | PRIMARY | 4 | wilsonar_hcsupplies.product_to_category.product_id | 1 | Using where | +----+-------------+----------------------+--------+---------------+---------+---------+-----------------------------------------------------+-------+---------------------------------+
答案 0 :(得分:0)
EXPLAIN告诉我们product_to_category有一个MySQL考虑使用的索引,因为possible_keys是“category_id”。但是,由于某种原因,它没有被使用。
“rows”是26343,“key”是NULL,这意味着MySQL必须扫描所有 每个产品的product_to_category中有26343行,即使使用连接缓冲区优化也会非常可怕。
product_to_category Table (26283 rows)
ptc_id | product_id | category_id
33797 | 20381 | 29
ptc_id没用,因为此表的主键应该是(category_id,product_id),并且(product_id,category_id)上添加了UNIQUE索引以优化搜索。这让我怀疑数据库结构,因此我打赌设计者使用了错误的类型(即除了INT之外的任何东西)用于其中一个表中的一列。因此,请检查您的列类型是否为tinyint,smallint,bigint,unsigned,等等......
其他原因是名为category_id的索引实际上并未对列category_id编制索引。你永远都不会知道。请检查。
现在,查询还有另一个问题,即GROUP BY使整个查询无效。我想知道这个查询应该做什么......
答案 1 :(得分:0)
(我还没有看到有用的“个人资料”。)
即使没有看到*
{
margin: 0;
padding: 0;
-ms-box-sizing: border-box;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
html, body
{
height: 100%;
color: #0068ac;
}
body {
text-align: center;
background: #689976;
}
.col-6-{width: 48%;}
body
{
background: gray;
}
#base
{
display: inline-block;
padding-top: 5%;
height: 90%;
/* width: 90%; */
}
#form
{
height: 98%;
background: #E6F0F7;
border-radius: 0 0 5px 5px;
}
#banner a
{
text-decoration: none;
outline: none;
display: block;
float: left;
font-size: 12px;
line-height: 36px;
position: relative;
padding: 0 10px 0 60px;
color: #ffe143;
background: #32a252;
height: 2em;
}
.col-6-
{
display: inline-block;
}
#form div div
{
text-align: left;
vertical-align: top;
padding: 1%;
}
#form div p
{
word-break: break-all;
}
的表结构,我怀疑它是缺陷部分。
product_to_category
ptc_id
PRIMARY KEY(product_id, category_id)
Further discussion最优的多个:许多映射表。
此外,还有INDEX(category_id, product_id)
。可以使用或不使用此复合索引,具体取决于这些列的基数。如果有用,那将是非常有益的。如果没有,则需要进行表扫描。
摆脱最后两个join()s - 你不使用那些表。 MySQL正在加入以确保它们存在,但浪费时间这样做。
一旦摆脱了两个不必要的表,就可以摆脱INDEX(upsell, status)
。
但是,为什么要轻触GROUP BY
?摆脱它,摆脱categories
。
所以这就是你需要的是上面的索引,再加上
products_to_categories
但是,等等!这不起作用,因为没有SELECT id, title, image, category, price, rrp
FROM `products`
WHERE `upsell` = 1
AND `status` = 1
。
为什么有时快?您已打开“查询缓存”。当任何更改任何相关表之前第二次运行相同的查询时,它将从QC中获取,通常在一毫秒左右。