如何优化我的MySQL Select查询?

时间:2015-07-10 07:17:06

标签: java mysql

我有一个MySQL数据库表,其格式如下:

CREATE TABLE IF NOT EXISTS data_packet (
  id BIGINT NOT NULL AUTO_INCREMENT,
  time_received BIGINT NOT NULL,
  content TEXT NOT NULL,
  recording_id INT NOT NULL,
  PRIMARY KEY (id),
  INDEX fk_data_packet_recording_idx (recording_id ASC),
  CONSTRAINT fk_data_packet_recording
    FOREIGN KEY (recording_id)
    REFERENCES recording(id)
)

在这张表中,我有这样的数据:

<Dat url="vehicleSpeed">
   <Abs name="speed" val="97"/>
   <Enm name="unit" val="kmh"/>
   <Enm name="state" val="valid"/>
</Dat>

该表最多可包含1.000.000行。现在我有了下面的查询,选择具有特定URL的特殊数据包。每个数据包都有这样的url属性。

SELECT * 
FROM data_packet 
WHERE recording_id = 1 
    AND content LIKE '%vehicleSpeed%' 
    AND time_received BETWEEN 1435843095338 AND 1435843095996 
ORDER BY time_received ASC;

我认为这个星座可以优化。在MySQL工作台中,此查询需要47毫秒,其中表只包含大约35.000行。 Java应用程序稍后将执行查询,我注意到,通过JDBC执行它需要更多时间。

您可以推荐哪种优化? 指数?另一栏?另一张桌子?

非常感谢。

2 个答案:

答案 0 :(得分:0)

任何查询优化大拇指规则都表示您可能希望在where子句中放置相同序列的INDEX。我建议创建一个包含两列(content,time_received)的INDEX,然后在mySQL中使用EXPLAIN命令检查性能。

ALTER TABLE data_packet 
  ADD  INDEX `IDX_COMPOSITE` (content,time_received);

EXPLAIN SELECT * 
FROM data_packet 
WHERE recording_id = 1 
    AND content LIKE '%vehicleSpeed%' 
    AND time_received BETWEEN 1435843095338 AND 1435843095996 
ORDER BY time_received ASC;

也可以尝试不分拣

EXPLAIN SELECT * 
FROM data_packet 
WHERE recording_id = 1 
    AND content LIKE '%vehicleSpeed%' 
    AND time_received BETWEEN 1435843095338 AND 1435843095996 

由于 了Anant

答案 1 :(得分:0)

你有一个关于recording_id的索引,但是你没有一个也包含time_received的索引。根据recording_id的值的数量和它们覆盖的时间范围,这可能会产生重大影响。

添加一个涵盖recording_id和time_received的索引。

第二个主要问题是您的查询使用LIKE,与具有前导通配符的值进行比较。没有索引可以帮助解决这个问题。您可以尝试使用FULLTEXT索引,然后使用MATCH()... AGAINST尝试找到匹配的值。

但是我建议重组数据库可能会更好。但这在很大程度上取决于存储在内容字段中的数据片段。如果它们都包含url字段,那么我可能只将它存储在内容字段中(这样你可以直接检查它而不需要if),然后将每个其他字段存储在另一个表中,你可以将它们连接到data_packet表。