speed up most recent query

CuriousDeveloper :

I am trying to get the 3 successful (success =1) recent records and then see their average response time.

I have manipulated the results so that the average response is always 2ms.

I have 20,000 records in this table right now, but I plan on have 1-2 million. It takes 40 seconds just with 20,000 records, so I need to optimize this query.

Here is the fiddle: http://sqlfiddle.com/#!9/dc91eb/1/0

The fiddle contains my indices too, so I am open to adding more indices if needed.


SELECT proxy, 
       Avg(a.responsems) AS avgResponseMs,
       COUNT(*) as Count
FROM proxylog a
WHERE  
        a.success = 1 
         AND ( (SELECT Count(0) 
                FROM   proxylog b 
                WHERE  ( ( b.success = a.success ) 
                         AND ( b.proxy = a.proxy ) 
                         AND ( b.datetime >= a.datetime ) )) <= 3 ) 
GROUP  BY proxy 
ORDER BY avgResponseMs

Here is the result of EXPLAIN

+----+--------------------+-------+-------+----------------+-------+---------+---------------------+-------+----------------------------------------------+
| id | select_type        | table | type  | possible_keys  | key   | key_len | ref                 | rows  | Extra                                        |
+----+--------------------+-------+-------+----------------+-------+---------+---------------------+-------+----------------------------------------------+
| 1  | PRIMARY            | a     | index | NULL           | proxy | 61      | NULL                | 19110 | Using where; Using temporary; Using filesort |
+----+--------------------+-------+-------+----------------+-------+---------+---------------------+-------+----------------------------------------------+
| 2  | DEPENDENT SUBQUERY | b     | ref   | proxy,datetime | proxy | 52      | wwwim_iroom.a.proxy | 24    | Using where; Using index                     |
+----+--------------------+-------+-------+----------------+-------+---------+---------------------+-------+----------------------------------------------+

Before you suggest windowed functions, I am using MariaDB 10.1.21 which is ~Mysql 5.6 AFAIK

CuriousDeveloper :

I was able to mimic row_number and follow @Gordon Linoff answer

SELECT pl.proxy, Avg(pl.responsems) AS avgResponseMs, COUNT(*) as Count
FROM (
      SELECT 
        @row_number:=CASE
        WHEN @g = proxy 
            THEN @row_number + 1
            ELSE 1
        END AS RN,
        @g:=proxy g,
        pl.*
      FROM proxyLog pl,
      (SELECT @g:=0,@row_number:=0) as t
      WHERE pl.success = 1 
      ORDER BY proxy,datetime DESC
) pl
WHERE RN <= 3 
GROUP BY proxy 
ORDER BY avgResponseMs

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=216113&siteId=1