优化查询?

时间:2015-03-27 14:47:34

标签: mysql sql explain

我的查询运行时间为28.39秒。我该如何优化呢?

explain SELECT distinct UNIX_TIMESTAMP(timestamp)*1000 as timestamp,count(a.sig_name) as counter from event a,network n  where n.fsi='pays' and n.net=inet_ntoa(a.ip_src) group by date(timestamp) order by timestamp asc;
+----+-------------+-------+--------+---------------+---------+---------+--- ---+---------+---------------------------------+
| id | select_type | table | type   | possible_keys | key     | key_len | ref  | rows    | Extra                           |
+----+-------------+-------+--------+---------------+---------+---------+------+---------+---------------------------------+
|  1 | SIMPLE      | a     | ALL    | NULL          | NULL    | NULL    | NULL | 8177074 | Using temporary; Using filesort |
|  1 | SIMPLE      | n     | eq_ref | PRIMARY,fsi   | PRIMARY | 77      | func |       1 | Using where                     |
+----+-------------+-------+--------+---------------+---------+---------+------+---------+---------------------------------+

2 个答案:

答案 0 :(得分:2)

因此,通常查看您的查询,我们发现表event a正在检查8,177,074行。这可能是缓慢的“根”,所以我们想看看如何使用索引减少搜索空间。

event a的主要条件是

n.net=inet_ntoa(a.ip_src)

这里的问题是我们需要在a.ip_src的每一行上执行计算(inet_ntoa),因此除了扫描整个表之外别无选择。一个可能更好的解决方案是反转比较并确保a.ip_src被索引。

a.ip_src=inet_aton(n.net)

如果我们在n中匹配的行数少于a中的行数,则效果会更好。如果不是这种情况,您应该认真考虑在表中缓存此函数的结果并在其上创建索引。

最后我猜测时间戳列在event a中,在这种情况下,索引可能有助于排序和分组,但可能没有。您可以在(ip_src,timestamp)

上尝试multi_column索引

答案 1 :(得分:0)

实践是在可以在WHERE/JOIN子句中使用的列上引入至少索引。我使用过至少是因为在很多情况下应该尝试使用PRIMARY/FOREIGN KEY关系。因此,如果某些东西已经是主/外键,则无需进一步索引。

通过以下查询引入INDEX可以简单地改进上述查询:

ALTER TABLE events ADD INDEX idx_ev_ipsrc (ip_src);

此处idx_ev_ipsrc =索引键的名称,而ip_src是要编制索引的列。

进一步提升:

使用以下查询在网络表上引入多列索引:

ALTER TABLE network ADD INDEX idx_net_fsi_net (fsi,net);

以上情况会导致行数甚至很少。

注意:以上查询适用于MySql,可以轻松地为其他数据库量身定制。