So I found two notable entries in my slow query log. The first:
Code: Select all
sql_text: DELETE cust, bind FROM customer_1_tbl cust, customer_1_binding_tbl bind WHERE cust.customer_id=bind.customer_id AND bind.user_status=5 AND bind.change_date < date_sub(curdate(), interval 30 day)
query_time: 00:01:19
Code: Select all
mysql> explain DELETE cust, bind FROM customer_1_tbl cust, customer_1_binding_tbl bind WHERE cust.customer_id=bind.customer_id AND bind.user_status=5 AND bind.change_date < date_sub(curdate(), interval 30 day);
+----+-------------+-------+--------+----------------------------+---------+---------+--------------------------+----------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+--------+----------------------------+---------+---------+--------------------------+----------+-------------+
| 1 | SIMPLE | bind | ALL | cust_1_bind_un,customer_id | NULL | NULL | NULL | 27766623 | Using where |
| 1 | SIMPLE | cust | eq_ref | PRIMARY | PRIMARY | 4 | openemm.bind.customer_id | 1 | Using where |
+----+-------------+-------+--------+----------------------------+---------+---------+--------------------------+----------+-------------+
I'm guessing this is run at least once a day, or maybe hourly? I decided to add an index in customer_1_binding_tbl. See the improvement:
Code: Select all
mysql> alter table customer_1_binding_tbl add index (user_status, change_date, customer_id);
mysql> explain DELETE cust, bind FROM customer_1_tbl cust, customer_1_binding_tbl bind WHERE cust.customer_id=bind.customer_id AND bind.user_status=5 AND bind.change_date < date_sub(curdate(), interval 30 day);
+----+-------------+-------+--------+----------------------------------------+-------------+---------+--------------------------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+--------+----------------------------------------+-------------+---------+--------------------------+------+-------------+
| 1 | SIMPLE | bind | range | cust_1_bind_un,customer_id,user_status | user_status | 9 | NULL | 1 | Using where |
| 1 | SIMPLE | cust | eq_ref | PRIMARY | PRIMARY | 4 | openemm.bind.customer_id | 1 | Using where |
+----+-------------+-------+--------+----------------------------------------+-------------+---------+--------------------------+------+-------------+
2 rows in set (0.00 sec)
mysql> DELETE cust, bind FROM customer_1_tbl cust, customer_1_binding_tbl bind WHERE cust.customer_id=bind.customer_id AND bind.user_status=5 AND bind.change_date < date_sub(curdate(), interval 30 day);
Query OK, 0 rows affected (0.03 sec)
The second happens when I click on the "Recipients" tab:
Code: Select all
sql_text: SELECT COUNT(*) FROM customer_1_tbl cust
query_time: 00:01:45
I decided to choose a specific mailing list that has around 7M recipients and saw:
Code: Select all
sql_text: SELECT COUNT(*) FROM customer_1_tbl cust WHERE (cust.customer_id in (SELECT customer_id FROM customer_1_binding_tbl bind WHERE (bind.mailinglist_id = 1)))
query_time: 00:00:53
This might be too late for the 2014 release because it will be a major change but I suggest you reevaluate if you really need an exact count every time the page is listed. In my opinion, making the user wait for a minute or so just to show that number on the page is not worth it. I would instead have a summary/statistics table that has the count as of a certain time (maybe updated daily) and display that number with a disclaimer and then maybe give the user the ability to refresh the summary counts when he needs an accurate number.
More to come
