0

我有 80k 多个客户,有 4 个小组。现在我想在 mysql 中找到 2 组用户进行查询。我的查询如下:

select c.customers_firstname as recipient_firstname, 
       c.customers_lastname as  recipient_lastname,
       c.customers_id as recipient_id, 
       c.customers_email_address as recipient_email_address 
from customers c
where customers_group_id = '1' OR customers_group_id = '3'

当我在 phpmyadmin 中运行此查询时,我得到了结果:显示第 0 - 29 行(总共 59,815 行,查询耗时 0.0034 秒)

ORDER BY recipient_firstname ASC但是当我在这个查询中添加 order by时,结果时间是:显示行 0 - 29(总共 59,815,查询耗时 0.2607 秒)

查询顺序为结果花费了太多时间。

我想通过查询减少订购时间。

如果有另一种方法可以在更短的时间内获得相同的结果,请提供帮助。

4

4 回答 4

3

您必须在customers_firstname字段上建立索引:这将加快ORDER BY但也会减慢WHERE(现在可能已编制索引)。

所以索引必须是customers_group_id, customers_firstname这个顺序。

CREATE INDEX my_query_ndx 
    ON customers ( customers_group_id, customers_firstname );

理论上,您可以将索引扩大为覆盖索引,并在两个关键字段之后包含您需要的所有其他字段SELECT。但是,维护这种索引很昂贵。你必须平衡优点和缺点。如果表非常“宽”,则对组 id、名字、姓氏、id 和电子邮件进行索引可能是有利的。

小的(或不那么小的)查询改进

where customers_group_id = '1' OR customers_group_id = '3'

为了清楚起见,可以将其重写为(它不会改变任何内容)为

WHERE customers_group_id IN ('1','3')

但是现在,要么customer_group_id是整数字段,要么不是。如果是,那么最好这样处理:

WHERE customers_group_id IN (1, 3)

在某些情况下,您可以提前计划您的 ID,例如第 3 组实际上是第 2 组,即您可能感兴趣的组是连续的。这样,您可以将查询重写为variable < valueorvariable > valuevariable BETWEEN,其速度是 的两倍OR。使用大型OR集,您可以轻松获得 4 倍的加速。

如果它不是一个整数字段,那么一定要努力使它成为一个。整数性能(和索引大小)将受益匪浅(但请注意,对于字符串,'3' 大于 '12',就像 'C' 大于 'AB';因此,类型转换不一定没有边影响)。

于 2013-10-18T07:00:58.907 回答
3

您需要该recipient_firstname字段的索引(所以真的是customers.customers_firstname)。索引允许对结果集进行有序的线性时间迭代。

如果没有索引,则必须对结果集进行聚合然后排序。这种排序将是n log n。对于大型集合来说,这显然很慢,如果它不能放入内存(60k 记录可能不取决于配置),它将执行一个非常慢的基于文件的排序。

tl;博士你需要一个索引。上的索引recipient_firstname将使查询在性能上非常接近非ORDER BY版本。


顺便说一句,如果customers_group_id 是一个整数字段,请使用整数文字,而不是字符串。它可能不会产生影响,但它具有误导性,实际上在某些情况下它很重要。


根据具体情况,可能还值得在组 ID 上放置一个索引。对于小集合,可以在构建集合时过滤结果,但对于大结果集,最终需要进行相当大的磁盘全表扫描。

于 2013-10-18T06:51:13.413 回答
1

尝试创建索引(customers_group_id, customers_firstname)- 这应该可以。

于 2013-10-18T06:53:17.293 回答
0

您需要在应用 order by 子句的列上创建索引。

CREATE INDEX index_name ON customers (customers_firstname);
于 2013-10-18T06:51:14.970 回答