There are a few things gonig on, but mainly it is the ORs that are killing
you.

As your  require OR to examine two distinct columns, both of equal relevance
to the query, MySQL: is left with no choice but to do a full table scan on
what might be (at a guess) a very larger table.  No amount of indexing will
fix this for the query presented.

You would be better off writing it as two distinct queires, each concerned
with conditions on a single column (open_dt and close_dt) and then UNIONing
the results. In this form, the indexes have a chance of being engaged.

Once the indexes are engaged, you probably want to your DATE/DATETIME
strings into actual DATEs or DATATIMEs, thus:

 ...
       (open_dt >= DATE('2011-08-30 00:00:00'))
 ...

In it's current state, the DATE fields are being converted to strings
implicitly for every row tested which further frustrates index usage as the
index is against the quasi-numeric DATE, not the string representation which
your current implementation appears to expect.  This query would also
suddenly begin to fail entirely if the DEFAULT_DATE_FORMAT gets modified by
an admin or a future release of MySQL.  The explicit casting I have
suggested will protect you against that,

 - michael dykman`
On Tue, Aug 30, 2011 at 12:45 PM, Brandon Phelps <bphe...@gls.com> wrote:

> Hello,
>
> I have the following query I'd like to optimize a bit:
>
> SELECT
>        sc.open_dt,
>        sc.close_dt,
>        sc.protocol,
>        INET_NTOA( sc.src_address ) AS src_address,
>        sc.src_port,
>        INET_NTOA( sc.dst_address ) AS dst_address,
>        sc.dst_port,
>        sc.sent,
>        sc.rcvd,
>        spm.desc AS src_port_desc,
>        dpm.desc AS dst_port_desc
> FROM firewall_connections AS sc
>        LEFT JOIN port_mappings AS spm ON spm.port = sc.src_port
>        LEFT JOIN port_mappings AS dpm ON dpm.port = sc.dst_port
> WHERE
>        (open_dt >= '2011-08-30 00:00:00' OR close_dt >= '2011-08-30
> 00:00:00')
>        AND (open_dt <= '2011-08-30 12:36:53' OR close_dt <= '2011-08-30
> 12:36:53')
> ORDER BY rcvd DESC
> LIMIT 0 , 10
>
> Currently I have an index on the rcvd column which seems to be working
> based on the output of EXPLAIN:
>
> id      select_type     table   type    possible_keys   key     key_len
>     ref     rows    Extra
> 1       SIMPLE  sc      index   open_dt         ndx_rcvd        4
> NULL    10      Using where
> 1       SIMPLE  spm     eq_ref  PRIMARY         PRIMARY         2
> syslog.sc.src_port      1
> 1       SIMPLE  dpm     eq_ref  PRIMARY         PRIMARY         2
> syslog.sc.dst_port      1
>
> However the query is still fairly slow for some reason, any ideas how I
> could speed it up with additional indexes, etc?
>
> The values I am using in the WHERE clause are variable and change each
> time.
>
> The table has around 23 million records right now but is expected to
> continue to grow up to a potential 150 million.
>
> Here is the table schema:
> CREATE TABLE IF NOT EXISTS `firewall_connections` (
>  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
>  `open_dt` datetime NOT NULL,
>  `close_dt` datetime NOT NULL,
>  `protocol` smallint(6) NOT NULL,
>  `src_address` int(10) unsigned NOT NULL,
>  `src_port` smallint(5) unsigned NOT NULL,
>  `dst_address` int(10) unsigned NOT NULL,
>  `dst_port` smallint(5) unsigned NOT NULL,
>  `sent` int(10) unsigned NOT NULL,
>  `rcvd` int(10) unsigned NOT NULL,
>  PRIMARY KEY (`id`),
>  KEY `ndx_rcvd` (`rcvd`),
>  KEY `ndx_sent` (`sent`)
> ) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
>
> Thanks in advance!
>
> --
> Brandon
>
> --
> MySQL General Mailing List
> For list archives: http://lists.mysql.com/mysql
> To unsubscribe:    
> http://lists.mysql.com/mysql?**unsub=mdyk...@gmail.com<http://lists.mysql.com/mysql?unsub=mdyk...@gmail.com>
>
>


-- 
 - michael dykman
 - mdyk...@gmail.com

 May the Source be with you.

Reply via email to