按查询排序需要花费太多时间

时间:2013-10-18 06:46:33

标签: php mysql sql

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

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添加订单时,结果时间为:显示0到29行(总计59,815,查询花费0.2607秒)

按查询的顺序对结果花费了太多时间。

我希望通过查询减少订单的时间。

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

4 个答案:

答案 0 :(得分:3)

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

如果您没有索引,则必须聚合结果集然后进行排序。这种排序将是n log n。对于大型集合而言,这显然相当慢,如果它无法适应内存(并且60k记录可能不依赖于配置),那么它将基于文件进行非常慢的排序。

tl; dr 您需要一个索引。 recipient_firstname上的索引会使查询在性能上与非ORDER BY版本非常接近。


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


根据具体情况,可能还需要在组ID上添加索引。对于小集合,结果可以在构建集合时进行过滤,但对于大型结果集,最终需要进行相当大量的全表扫描。

答案 1 :(得分: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,名字,姓氏,身份证和电子邮件进行索引可能是有利的。

小(或不小)查询改进

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 < valuevariable > valuevariable BETWEEN,其速度是OR的两倍。使用大OR个集合,您可以轻松获得4倍的加速。

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

答案 2 :(得分:1)

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

答案 3 :(得分:0)

您需要create index关于应用order by子句的列。

CREATE INDEX index_name ON customers (customers_firstname);