创建索引以优化慢速查询

时间:2011-03-29 12:38:37

标签: mysql sql optimization indexing

有一个查询在250,000行表上花费的时间太长。我需要加快速度:

create table occurrence (
occurrence_id int(11) primary key auto_increment,
client_id varchar(16) not null,
occurrence_cod varchar(50) not null,
entry_date datetime not null,
zone varchar(8) null default null
)
;

insert into occurrence (client_id, occurrence_cod, entry_date, zone)
values
('1116', 'E401', '2011-03-28 18:44', '004'),
('1116', 'R401', '2011-03-28 17:44', '004'),
('1116', 'E401', '2011-03-28 16:44', '004'),
('1338', 'R401', '2011-03-28 14:32', '001')
;

select client_id, occurrence_cod, entry_date, zone
from occurrence o
where
    occurrence_cod = 'E401'
    and
    entry_date = (
        select max(entry_date)
        from occurrence
        where client_id = o.client_id
    )
;
+-----------+----------------+---------------------+------+
| client_id | occurrence_cod | entry_date          | zone |
+-----------+----------------+---------------------+------+
| 1116      | E401           | 2011-03-28 16:44:00 | 004  |
+-----------+----------------+---------------------+------+
1 row in set (0.00 sec)

表结构来自商业应用程序,不能更改。

优化它的最佳指标是什么?或者更好的查询?

编辑:

这是每个客户端最后一次出现的E401代码,并且只有在最后一次出现时才是该代码。

6 个答案:

答案 0 :(得分:4)

此类查询的理想索引是:

index #1: [client_id] + [entry_date]
index #2: [occurence_cod] + [entry_date]

然而,如果数据具有某些特征,则可以简化这些索引。这将节省文件空间,也可以节省数据更新时间(插入/删除/更新)。

如果每个[client_id]很少有一个“出现”记录,那么索引#1只能是[client_id]。

同样地,如果每个[occurence_cod]很少有一个“出现”记录,那么索引#1只能是[occurence_cod]。

将索引#2转换为[entry_date] + [occurence_cod]可能更有用。这将使您能够将索引用于仅在[entry_date]上的条件。

问候,

答案 1 :(得分:1)

除非你真的想要获得具有最大日期的行,当且仅当occurrence与occurrence匹配时,这应该有效:

select client_id, occurrence_cod, entry_date, zone 
from occurrence o 
where occurrence_cod = 'E401'
ORDER BY entry_date DESC
LIMIT 1;

它将返回最新的行,其中包含occurrence __cod ='E401'

答案 2 :(得分:1)

我会重新编写查询:

select client_id, occurrence_cod, max(entry_date), zone
from occurrence 
group by client_id, occurrence_cod, zone;

(假设其他行确实相同,并且输入日期是唯一改变的行。)

答案 3 :(得分:1)

select 
  a.client_id, 
  a.occurrence_cod, 
  a.entry_date, 
  a.zone
from occurrence a 
  inner join (
    select client_id, occurence_cod, max(entry_date) as entry_date 
    from occurence
  ) as b
on 
  a.client_id = b.client_id and 
  a.occurence_cod = b.occurence_cod and 
  a.entry_date = b.entry_date

where
    a.occurrence_cod = 'E401'

使用这种方法,你要避免每行的子选择,比较两组大数据比组的每一行的大数据集要快。

答案 4 :(得分:0)

您是否尝试在occurrence_cod上添加索引?

答案 5 :(得分:0)

如果其他方法不可用,请尝试此操作。

  1. 创建一个新表:last_occurrence。
  2. 每次用户发生时,请更新此last_occurrence表中的相应行。
  3. 通过执行此操作,您只需使用以下sql来获取结果:)

      

    从last_occurrence

    中选择*