针对Prestashop 1.6优化MySQL
我正在VPS上运行Prestashop 1.6电动电子商店,具有4GB RAM、2CPU、60GB SSD特性。目前我的商店里有大约20000种产品,我的网站加载有问题,因为mysql查询运行时间很长。当我运行htop分析进程时,我发现mysql消耗了两个CPU的100%。这是mysqltuner的输出:针对Prestashop 1.6优化MySQL,mysql,query-optimization,prestashop,database-administration,mysqltuner,Mysql,Query Optimization,Prestashop,Database Administration,Mysqltuner,我正在VPS上运行Prestashop 1.6电动电子商店,具有4GB RAM、2CPU、60GB SSD特性。目前我的商店里有大约20000种产品,我的网站加载有问题,因为mysql查询运行时间很长。当我运行htop分析进程时,我发现mysql消耗了两个CPU的100%。这是mysqltuner的输出: -------- Performance Metrics ------------------------------------------------- [--] Up for: 1h 2
-------- Performance Metrics -------------------------------------------------
[--] Up for: 1h 29m 9s (241K q [45.109 qps], 319 conn, TX: 318M, RX: 126M)
[--] Reads / Writes: 78% / 22%
[--] Total buffers: 192.0M global + 2.7M per thread (151 max threads)
[OK] Maximum possible memory usage: 597.8M (15% of installed RAM)
[OK] Slow queries: 0% (8/241K)
[OK] Highest usage of available connections: 2% (4/151)
[OK] Key buffer size / total MyISAM indexes: 16.0M/44.9M
[OK] Key buffer hit rate: 99.6% (36M cached / 133K reads)
[OK] Query cache efficiency: 49.6% (101K cached / 205K selects)
[!!] Query cache prunes per day: 1386761
[OK] Sorts requiring temporary tables: 0% (1 temp sorts / 7K sorts)
[!!] Joins performed without indexes: 78
[OK] Temporary tables created on disk: 8% (846 on disk / 9K total)
[OK] Thread cache hit rate: 98% (4 created / 319 connections)
[!!] Table cache hit rate: 10% (340 open / 3K opened)
[OK] Open file limit used: 62% (643/1K)
[OK] Table locks acquired immediately: 100% (239K immediate / 239K locks)
-------- Recommendations -----------------------------------------------------
General recommendations:
Add skip-innodb to MySQL configuration to disable InnoDB
MySQL started within last 24 hours - recommendations may be inaccurate
Enable the slow query log to troubleshoot bad queries
Adjust your join queries to always utilize indexes
Increase table_cache gradually to avoid file descriptor limits
Variables to adjust:
query_cache_size (> 16M)
join_buffer_size (> 128.0K, or always use indexes with joins)
table_cache (> 400)
请建议任何优化方法
编辑:
慢速查询输出日志是。这是您日志中的第二个查询,查看其他查询。为了对此有所帮助,我稍微进行了重组,以摆脱子查询,并将其转换为内部联接。另外,为了帮助其他不了解您的表的人,请始终将字段引用限定为table.column或alias.column,以便了解level_depth、nleft和nright的来源。它可能有助于索引 对于索引,每个表都有以下内容
ps_category, index ON( active, id_category, id_lang, nleft, nright, level_depth )
ps_category_lang, index ON( id_category, id_shop, id_lang )
ps_category_shop, index ON( id_category, id_shop )
ps_category_group, index ON( id_category, id_group )
ps_lang, index ON( id_lang, active )
稍微重写的查询
SELECT
c.id_parent,
c.id_category,
cl.name,
cl.description,
cl.link_rewrite
FROM
ps_category c
INNER JOIN ps_category_lang cl
ON c.id_category = cl.id_category
AND cl.id_shop = 1
AND cl.id_lang = 2
INNER JOIN ps_category_shop cs
ON c.id_category = cs.id_category
AND cs.id_shop = 1
INNER JOIN ps_category_group psg
ON c.id_category = psg.id_category
AND psg.id_group = 1
WHERE
( c.active = 1
OR c.id_category = 2)
AND c.id_category != 1
AND level_depth <= 7
AND nleft >= 350 AND nright <= 351
ORDER BY
level_depth ASC,
cs.position ASC;
下一个查询您需要确认您真正想要什么。。。您有一个到语言表的左连接,但是在where子句中添加了“AND l.active=1”,这实际上将把它变成一个内部连接。如果您希望它真正成为左连接,请将l.active移动到连接零件,如我在此处调整的位置
SELECT
l.id_lang,
c.link_rewrite
FROM
ps_category_lang AS c
LEFT JOIN ps_lang AS l
ON c.id_lang = l.id_lang
AND l.active = 1
WHERE
c.id_category = 324
希望这些索引和查询的示例澄清/可读性能够帮助您改进日志。如果与其他人仍有问题,请根据需要发布
慢速日志报告中第一次查询的修订
在第一个查询中,您似乎在某个特定的产品商店外寻找产品。但是,您将以产品类别开始查询,然后加入产品,然后再加入产品商店。由于这些产品最终将通过where与特定类别相关联,因此它无论如何都会创建一个内部连接。我将稍微重组如下
我会有一个关于ps_产品_商店的索引(id_商店、活动、可见性、id_产品、id_类别_默认)
关于将多字段索引创建为单个索引,例如:
在ps_类别(活动、id_类别、id_类别、nleft、nright、level_深度)上创建索引act_id_lang
给出一个简单的索引名。。。在任何桌子上。。。使用所有密钥,因为它们将在查询中有效。使用较长时间后,您应该使用mysqltuner。 这将删除以下消息:
MySQL在过去24小时内启动-建议可能不准确,因此基本上你是在免费寻求专业的调优帮助,而且你不知道从哪里开始优化?获取一个缓慢的查询日志并发布影响性能的实际罪魁祸首SQL查询如何。一堆统计数据与没有看到写得糟糕的查询和已知的索引相比,可能真的是令人窒息的地方。我不知道我是否会同意如图所示的0%的慢速查询。请注意,没有索引的联接=78@DRapp这是慢速查询日志@N.B.的输出。如果我知道我不会问的话。无论是专业还是非专业,我都有学习的权利。当然,你有学习的权利,我永远不会质疑这一点。然而,你们发布了一个程序的输出,然后你们期望用勺子喂食吗?例如,程序告诉您:
启用慢速查询日志以排除错误查询的故障
。谷歌>“启用慢速查询日志以排除错误查询”>如果遇到问题,请在此处询问。这样看来,你似乎想为自己做一切,因为你问的问题没有足够的信息来帮助你。看起来您需要的是完整的解决方案,而不是解决问题的线索。对于第二个查询,我有查询时间:0.001116。为什么我需要优化它?第一个查询是长查询时间:11。635315@torayeff,我将回顾第一个查询,但索引本身应该会有所帮助,并且所编写的查询会向我显示/帮助我确定哪些索引可能最有助于全面帮助。我很快会回到第一个问题。@torayeff,那可能是。。。但是它们是单独的索引,还是我列出的所有字段的复合索引作为单个索引。。。查询时的结果完全不同。我可以让您访问我的phpmyadmin吗?这不是索引问题。没有令人满意的标准来使用任何指标,加上心脏病明显较低。这是一个简单的配置问题,他使用的是MyISAM引擎,数据库必须通过20k条记录。在磁盘上排序,即使是SSD,也比使用RAM慢。它也是一个网络商店,没有交易支持。这里有很多错误,这是个棘手的问题。我建议聘请一位专家,从长远来看,这要便宜得多,而且你显然不是来学习的。
SELECT
l.id_lang,
c.link_rewrite
FROM
ps_category_lang AS c
LEFT JOIN ps_lang AS l
ON c.id_lang = l.id_lang
AND l.active = 1
WHERE
c.id_category = 324
SELECT
p.*,
ps.*,
stock.out_of_stock,
IFNULL(stock.quantity, 0) as quantity,
MAX(pas.id_product_attribute) id_product_attribute,
pas.minimal_quantity AS product_attribute_minimal_quantity,
pl.description,
pl.description_short,
pl.available_now,
pl.available_later,
pl.link_rewrite,
pl.meta_description,
pl.meta_keywords,
pl.meta_title,
pl.name,
MAX(image_shop.id_image) id_image,
il.legend,
m.name AS manufacturer_name,
cl.name AS category_default,
DATEDIFF(ps.`date_add`, DATE_SUB(NOW(),INTERVAL 20 DAY)) > 0 AS new,
ps.price AS orderprice
FROM
( select @thisLanguage := 1 ) sqlvars,
ps_product_shop ps
INNER JOIN ps_product p
ON ps.id_product = p.id_product
INNER JOIN ps_category_product cp
ON id_product = cp.id_product
AND cp.id_category = 2
LEFT JOIN ps_product_attribute pa
ON p.id_product = pa.id_product
LEFT JOIN ps_product_attribute_shop pas
ON pa.id_product_attribute = pas.id_product_attribute
AND ps.id_shop = pas.id_shop
AND pas.default_on = 1
LEFT JOIN ps_stock_available stock
ON p.id_product = stock.id_product
AND ps.id_shop = stock.id_shop
AND stock.id_shop_group = 0
AND stock.id_product_attribute = IFNULL(pas.id_product_attribute, 0)
LEFT JOIN ps_product_lang pl
ON p.id_product = pl.id_product
AND ps.id_shop = pl.id_shop
AND pl.id_lang = @thisLanguage
LEFT JOIN ps_image i
ON p.id_product = i.id_product
LEFT JOIN ps_image_shop image_shop
ON i.id_image = image_shop.id_image
AND ps.id_shop = image_shop.id_shop
AND image_shop.cover = 1
LEFT JOIN ps_image_lang il
ON image_shop.id_image = il.id_image
AND il.id_lang = @thisLanguage
LEFT JOIN ps_manufacturer m
ON p.id_manufacturer = m.id_manufacturer
LEFT JOIN ps_category_lang cl
ON ps.id_category_default = cl.id_category
AND cl.id_shop = ps.id_shop
AND cl.id_lang = @thisLanguage
WHERE
ps.id_shop = 1
AND ps.active = 1
AND ps.visibility IN ("both", "catalog")
GROUP BY
ps.id_product
ORDER BY
cp.position ASC
LIMIT
0,8;