我有一个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执行它需要更多时间。
您可以推荐哪种优化? 指数?另一栏?另一张桌子?
非常感谢。
答案 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表。