0

I have got a MySQL database table, that has the following form:

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)
)

Inside this table I have got data like this:

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

The table can contain up to 1.000.000 rows. Now I have got queries like the one following, to select special data packets with a certain url. Every data packet has such a url attribute.

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

I think this constellation can be optimized. In MySQL workbench this query takes 47ms where the table only contains about 35.000 rows. A Java application shall execute the queries later and I noticed, that it takes more time to execute it via the JDBC.

What optimization can you recommend? Index? Another column? Another table?

Thank you very much.

tellob
  • 1,220
  • 3
  • 16
  • 32
  • There is no index on `time_received` that will surely help – Hanky Panky Jul 10 '15 at 07:20
  • What do you think of making an extra column, where I can store the url separate? What effect do indices have in detail? – tellob Jul 10 '15 at 07:24
  • You can make `Unique` constraint on table for the column `id`. As you have already done it like NOT NULL AUTO INCREMENT then you can apply this constraint to improve the performance. – ChiranjeeviIT Jul 10 '15 at 07:27

2 Answers2

0

Any query optimization thumb rule says you might want to have an INDEX in same sequence you are putting columns in where clause. I would suggest to create an INDEX with two columns (content,time_received) and then check performance with EXPLAIN command in mySQL.

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;

Also try without sorting

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

Thanks Anant

0

You have an index on recording_id, but you do not have one that also covers time_received. Depending on the number of values of recording_id and the time range they cover this could make a major difference.

Add an index that covers both recording_id AND time_received.

The 2nd major issue is that your query uses LIKE, comparing with a value which has a leading wildcard. No index in going to help with this. You could try using a FULLTEXT index, and then using MATCH()...AGAINST to try and find the matching values.

However I would suggest that it might be better to restructure your database. But this very much depends on the fragments of data that are stored in the content field. If all of them contain the url field then I would possibly just store that in the content field (so you can check it directly without the need for if), and then store each of the other fields in another table which you can join to the data_packet table.

Kickstart
  • 21,403
  • 2
  • 21
  • 33