MySQL 查询在 phpMyAdmin 中运行正常,但在 PHP 中挂起
MySQL query runs ok in phpMyAdmin but hangs in PHP
我有一个相当简单的查询,当我在 phpMyAdmin 中测试它时 运行没问题:
SELECT
c.customers_id,
c.customers_cid,
c.customers_gender,
c.customers_firstname,
c.customers_lastname,
c.customers_email_address,
c.customers_telephone,
c.customers_date_added,
ab.entry_company,
ab.entry_street_address,
ab.entry_postcode,
ab.entry_city,
COUNT(o.customers_id) AS orders_number,
SUM(ot.value) AS totalvalue,
mb.bonus_points
FROM
orders AS o,
orders_total AS ot,
customers AS c,
address_book AS ab,
module_bonus AS mb
WHERE
c.customers_id = o.customers_id
AND c.customers_default_address_id = ab.address_book_id
AND c.customers_id = mb.customers_id
AND o.orders_id = ot.orders_id
AND ot.class = 'ot_subtotal'
** AND c.customers_gender = 'm' AND c.customers_lastname LIKE 'Famlex'
GROUP BY o.customers_id
标有 ** 的行根据进行查询的应用程序的过滤设置而变化。
现在,当我在 phpMyAdmin 中对此进行测试时,查询需要几秒钟才能到达 运行(这很好,因为有数千个条目,据我所知,在使用 COUNT 和SUM 索引没有帮助)并且结果是完美的,但是当我 运行 在 PHP 中完全相同的查询(在 运行ning 之前回显)时,MySQL 线程加载一个核心到100%,直到我杀了它才停止。
如果我去除额外的东西来计算 COUNT 和 SUM,查询完成但结果对我没有用。
解释:
1 SIMPLE mb ALL NULL NULL NULL NULL 48713 Using temporary; Using filesort
1 SIMPLE ot ALL idx_orders_total_orders_id NULL NULL NULL 811725 Using where
1 SIMPLE o eq_ref PRIMARY PRIMARY 4 db.ot.orders_id 1 Using where
1 SIMPLE c eq_ref PRIMARY PRIMARY 4 db.o.customers_id 1 Using where
1 SIMPLE ab eq_ref PRIMARY PRIMARY 4 db.c.customers_default_address_id 1
EXPLAIN 在应用索引和使用连接后:
1 SIMPLE c ref PRIMARY,search_str_idx search_str_idx 98 const 1 Using where; Using temporary; Using filesort
1 SIMPLE mb ALL NULL NULL NULL NULL 48713 Using where
1 SIMPLE ab eq_ref PRIMARY PRIMARY 4 db.c.customers_default_address_id 1
1 SIMPLE ot ref idx_orders_total_orders_id,class class 98 const 157004 Using where
1 SIMPLE o eq_ref PRIMARY PRIMARY 4 db.ot.orders_id 1 Using where
使用显式连接而不是隐式连接
SELECT
c.customers_id,
c.customers_cid,
c.customers_gender,
c.customers_firstname,
c.customers_lastname,
c.customers_email_address,
c.customers_telephone,
c.customers_date_added,
ab.entry_company,
ab.entry_street_address,
ab.entry_postcode,
ab.entry_city,
COUNT(o.customers_id) AS orders_number,
SUM(ot.value) AS totalvalue,
mb.bonus_points
FROM
orders o
join orders_total ot on o.orders_id = ot.orders_id
join customers c on c.customers_id = o.customers_id
join address_book ab on c.customers_default_address_id = ab.address_book_id
join module_bonus mb on c.customers_id = mb.customers_id
where
ot.class = 'ot_subtotal'
c.customers_gender = 'm'
AND c.customers_lastname = 'Famlex'
GROUP BY o.customers_id
假设所有连接键也是这些表的主键,即:
o.orders_id, c.customers_id, ab.address_book_id
如果尚未添加以下索引,您将需要添加它们
alter table orders add index customers_id_idx(customers_id);
alter table module_bonus add index customers_id_idx(customers_id);
alter table orders_total add index orders_id_idx(orders_id);
alter table orders_total add index orders_class_idx(class);
alter table customers add index search_str_idx(customers_gender,customers_lastname);
确保在应用索引之前对表进行备份。
能否分享 SQL 转储的记录,以便我查看?
phpMyAdmin 自动向 select 查询添加 limit 子句,这就是为什么我认为您认为在 phpMyAdmin 查询中 运行 很好但不是通过你 PHP 脚本。
尝试在 运行 之前在 phpMyAdmin 中的查询中添加显式限制子句说 limit 0, 1000 ,看看这是否会使 phpMyAdmin 的性能变慢。
我有一个相当简单的查询,当我在 phpMyAdmin 中测试它时 运行没问题:
SELECT
c.customers_id,
c.customers_cid,
c.customers_gender,
c.customers_firstname,
c.customers_lastname,
c.customers_email_address,
c.customers_telephone,
c.customers_date_added,
ab.entry_company,
ab.entry_street_address,
ab.entry_postcode,
ab.entry_city,
COUNT(o.customers_id) AS orders_number,
SUM(ot.value) AS totalvalue,
mb.bonus_points
FROM
orders AS o,
orders_total AS ot,
customers AS c,
address_book AS ab,
module_bonus AS mb
WHERE
c.customers_id = o.customers_id
AND c.customers_default_address_id = ab.address_book_id
AND c.customers_id = mb.customers_id
AND o.orders_id = ot.orders_id
AND ot.class = 'ot_subtotal'
** AND c.customers_gender = 'm' AND c.customers_lastname LIKE 'Famlex'
GROUP BY o.customers_id
标有 ** 的行根据进行查询的应用程序的过滤设置而变化。
现在,当我在 phpMyAdmin 中对此进行测试时,查询需要几秒钟才能到达 运行(这很好,因为有数千个条目,据我所知,在使用 COUNT 和SUM 索引没有帮助)并且结果是完美的,但是当我 运行 在 PHP 中完全相同的查询(在 运行ning 之前回显)时,MySQL 线程加载一个核心到100%,直到我杀了它才停止。
如果我去除额外的东西来计算 COUNT 和 SUM,查询完成但结果对我没有用。
解释:
1 SIMPLE mb ALL NULL NULL NULL NULL 48713 Using temporary; Using filesort
1 SIMPLE ot ALL idx_orders_total_orders_id NULL NULL NULL 811725 Using where
1 SIMPLE o eq_ref PRIMARY PRIMARY 4 db.ot.orders_id 1 Using where
1 SIMPLE c eq_ref PRIMARY PRIMARY 4 db.o.customers_id 1 Using where
1 SIMPLE ab eq_ref PRIMARY PRIMARY 4 db.c.customers_default_address_id 1
EXPLAIN 在应用索引和使用连接后:
1 SIMPLE c ref PRIMARY,search_str_idx search_str_idx 98 const 1 Using where; Using temporary; Using filesort
1 SIMPLE mb ALL NULL NULL NULL NULL 48713 Using where
1 SIMPLE ab eq_ref PRIMARY PRIMARY 4 db.c.customers_default_address_id 1
1 SIMPLE ot ref idx_orders_total_orders_id,class class 98 const 157004 Using where
1 SIMPLE o eq_ref PRIMARY PRIMARY 4 db.ot.orders_id 1 Using where
使用显式连接而不是隐式连接
SELECT
c.customers_id,
c.customers_cid,
c.customers_gender,
c.customers_firstname,
c.customers_lastname,
c.customers_email_address,
c.customers_telephone,
c.customers_date_added,
ab.entry_company,
ab.entry_street_address,
ab.entry_postcode,
ab.entry_city,
COUNT(o.customers_id) AS orders_number,
SUM(ot.value) AS totalvalue,
mb.bonus_points
FROM
orders o
join orders_total ot on o.orders_id = ot.orders_id
join customers c on c.customers_id = o.customers_id
join address_book ab on c.customers_default_address_id = ab.address_book_id
join module_bonus mb on c.customers_id = mb.customers_id
where
ot.class = 'ot_subtotal'
c.customers_gender = 'm'
AND c.customers_lastname = 'Famlex'
GROUP BY o.customers_id
假设所有连接键也是这些表的主键,即:
o.orders_id, c.customers_id, ab.address_book_id
如果尚未添加以下索引,您将需要添加它们
alter table orders add index customers_id_idx(customers_id);
alter table module_bonus add index customers_id_idx(customers_id);
alter table orders_total add index orders_id_idx(orders_id);
alter table orders_total add index orders_class_idx(class);
alter table customers add index search_str_idx(customers_gender,customers_lastname);
确保在应用索引之前对表进行备份。
能否分享 SQL 转储的记录,以便我查看?
phpMyAdmin 自动向 select 查询添加 limit 子句,这就是为什么我认为您认为在 phpMyAdmin 查询中 运行 很好但不是通过你 PHP 脚本。 尝试在 运行 之前在 phpMyAdmin 中的查询中添加显式限制子句说 limit 0, 1000 ,看看这是否会使 phpMyAdmin 的性能变慢。