mysql 查询从 10,000 条数据中检索太慢(查询优化)

mysql query retrieve too slow from 10,000 of data (Query Optimizing)

10,000 条会员、会员和付款方面的数据 table。检索查询太慢,同时在每个成员最新付款中搜索特定付款状态。

SELECT m.id AS member_id, m.full_name, m.unit, m.street, m.block, m.country,   m.postal_code, cat . * , cat.id AS cat_id, mem.membership_num, mem.id AS membership_id
FROM memberships mem
LEFT JOIN category cat ON mem.category_id = cat.id
LEFT JOIN members m ON mem.member_id = m.id
WHERE m.id >0
AND m.status = 'active'
AND (
  mem.category_id
  BETWEEN 1
  AND 11
)
AND (
  SELECT p1.payment_status_id
  FROM payments p1
  WHERE p1.category_id = cat.id
  AND p1.member_id = mem.member_id
  AND p1.payment_status_id = '1'
  LIMIT 1
  ) != ''
GROUP BY CONCAT( cat.id, '_', m.unit, '_', m.postal_code )
ORDER BY m.full_name ASC
LIMIT 0 , 25

解释

查询运行太慢 21.00 秒到 99.00 秒

首先确保您已经为JOINS 和WHERE 子句中涉及的所有列创建了索引。此外,如果您创建了复合索引,请确保它们的顺序与查询中的顺序相同。尝试以下操作,看看是否有任何不同:

SELECT m.id AS member_id, 
         m.full_name, 
         m.unit, 
         m.street, 
         m.block, 
         m.country,   
         m.postal_code, 
         cat . * , 
         cat.id AS cat_id, 
         mem.membership_num, 
         mem.id AS membership_id
FROM memberships mem
LEFT JOIN members m ON  m.id = mem.member_id
LEFT JOIN category cat ON cat.id = mem.category_id
INNER JOIN payments p1 ON p1.category_id = mem.category_id
                          AND p1.member_id = mem.member_id 
                          AND p1.payment_status_id = '1'
WHERE m.id > 0
AND mem.category_id BETWEEN 1 AND 11
AND m.status = 'active'
GROUP BY CONCAT( cat.id, '_', m.unit, '_', m.postal_code )
ORDER BY m.full_name ASC
LIMIT 0 , 25


问题

mysql 查询中的页面速度变慢(3-5 分钟而不是几秒),这些查询具有多个连接和子查询以在 table 中检索大量数据(~10,000)秒。


解决方案 - 使用列索引

添加了索引并进行了各种搜索查询,检索效果更好。


注释

索引用于快速查找具有特定列值的行。如果没有索引,MySQL 必须从第一行开始,然后通读整个 table 以找到相关行。 table越大,成本越高。如果 table 有相关列的索引,MySQL 可以快速确定要在数据文件中间查找的位置,而无需查看所有数据。这比顺序读取每一行要快得多。

提高SELECT 操作性能的最佳方法是在查询中测试的一个或多个列上创建索引。索引条目就像指向 table 行的指针,允许查询快速确定哪些行与 WHERE 子句中的条件匹配,并检索这些行的其他列值。所有 MySQL 数据类型都可以被索引。

eg: ALTER TABLE `memberships` ADD INDEX ( `category_id` ) ;

缺点:索引是一些额外的东西,您可以在 MySQL table 上启用它来提高性能,但它们确实有一些缺点。当您创建新索引时,MySQL 会构建一个单独的信息块,每次对 table 进行更改时都需要更新该信息块。这意味着如果您不断更新、插入和删除 table 中的条目,这可能会对性能产生负面影响。

教程mysql.com, howtoforge.com, tizag.com


谢谢

@venca @Boris @Raja Amer Khan 和所有

感谢大家帮我解决问题。