|
ANALYZE TABLE has never been executed on 10.0.20, so cardinality is unknown
SHOW INDEX on 10.0.20
| Table |
Non_unique |
Key_name |
Seq_in_index |
Column_name |
Collation |
Cardinality |
| versioned_params |
0 |
PRIMARY |
1 |
object_id |
A |
NULL |
| versioned_params |
0 |
PRIMARY |
2 |
time_id |
A |
NULL |
| versioned_params |
0 |
PRIMARY |
3 |
param_id |
A |
NULL |
| versioned_params |
0 |
PRIMARY |
4 |
counter |
A |
24300823203 |
| versioned_params |
1 |
second_idx |
1 |
object_id |
A |
NULL |
| versioned_params |
1 |
second_idx |
2 |
param_id |
A |
NULL |
| versioned_params |
1 |
second_idx |
3 |
device_time |
A |
NULL |
| versioned_params |
1 |
second_idx |
4 |
time_id |
A |
NULL |
SHOW INDEX on 10.0.26
| Table |
Non_unique |
Key_name |
Seq_in_index |
Column_name |
Collation |
Cardinality |
| versioned_params |
0 |
PRIMARY |
1 |
object_id |
A |
360774 |
| versioned_params |
0 |
PRIMARY |
2 |
time_id |
A |
398454726 |
| versioned_params |
0 |
PRIMARY |
3 |
param_id |
A |
4861147661 |
| versioned_params |
0 |
PRIMARY |
4 |
counter |
A |
24305738307 |
| versioned_params |
1 |
second_idx |
1 |
object_id |
A |
388531 |
| versioned_params |
1 |
second_idx |
2 |
param_id |
A |
9916661 |
| versioned_params |
1 |
second_idx |
3 |
device_time |
A |
24305738307 |
| versioned_params |
1 |
second_idx |
4 |
time_id |
A |
24305738307 |
|
|
whitewind Check out https://jira.mariadb.org/browse/MDEV-10503 in case it is related. I had similar problems until I did an analyze across my TokuDB tables to fix cardinality and row counts.
|
|
Isn't the issue described here an opposite of MDEV-10503?
There, the problem is that cardinality is always 0, and it can create all kinds of trouble; here, cardinality is actually calculated on the recent version, but performance drops.
Although, is it the right cardinality? Does the table really have over 24 bln rows?
|
|
Indeed, it may be opposite of MDEV-10503.
The table really has 24 bln rows, but first columns of indices has only approximate cardinality because of finite tokudb_analyze_time. Actually there are about 4k unique object_id's and about 160k unique combinations of object_id and param_id
|
|
whitewind,
So, how slower has it actually become with the new plan? And did the query return identical correct results on both versions?
While the first plan claims there would be only one row to examine, it is obviously not so.
|
|
SELECT SQL_NO_CACHE object_id, param_id, MAX(device_time) AS device_time FROM versioned_params WHERE 1 AND object_id IN (0,1782) AND device_time < '2016-08-08 16:00:00.000' GROUP BY object_id, param_id;
|
10.0.20:
- First run: 23 rows in set (0.53 sec)
- Second run:23 rows in set (0.00 sec)
10.0.26:
- First run: 23 rows in set (8.49 sec)
- Second run: 23 rows in set (6.73 sec)
|
|
whitewind,
Did you run ANALYZE on 10.0.26?
With my artificial data I'm also getting the same different plans on 10.0.20 vs 10.0.26, but after ANALYZE 10.0.26 gets back to the same plan with 'Using where; Using index for group-by". But my table is much slower (500K rows), so there is no distinct difference in execution time, thus I can't confirm that performance gets back to normal after ANALYZE:
MariaDB [test]> select count(*) from versioned_params;
|
+----------+
|
| count(*) |
|
+----------+
|
| 543200 |
|
+----------+
|
1 row in set (1.65 sec)
|
|
10.0.20
|
MariaDB [test]> EXPLAIN SELECT object_id, param_id, MAX(device_time) AS device_time FROM versioned_params WHERE 1 AND object_id IN (0,1782) AND device_time < '2016-08-08 16:00:00.000' GROUP BY object_id, param_id;
|
+------+-------------+------------------+-------+--------------------+------------+---------+------+------+---------------------------------------+
|
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
|
+------+-------------+------------------+-------+--------------------+------------+---------+------+------+---------------------------------------+
|
| 1 | SIMPLE | versioned_params | range | PRIMARY,second_idx | second_idx | 15 | NULL | 1 | Using where; Using index for group-by |
|
+------+-------------+------------------+-------+--------------------+------------+---------+------+------+---------------------------------------+
|
1 row in set (0.25 sec)
|
|
MariaDB [test]> SELECT object_id, param_id, MAX(device_time) AS device_time FROM versioned_params WHERE 1 AND object_id IN (0,1782) AND device_time < '2016-08-08 16:00:00.000' GROUP BY object_id, param_id;
|
....
|
935 rows in set (0.23 sec)
|
MariaDB [test]> analyze table versioned_params;
|
+-----------------------+---------+----------+----------+
|
| Table | Op | Msg_type | Msg_text |
|
+-----------------------+---------+----------+----------+
|
| test.versioned_params | analyze | status | OK |
|
+-----------------------+---------+----------+----------+
|
1 row in set (9.02 sec)
|
MariaDB [test]> EXPLAIN SELECT object_id, param_id, MAX(device_time) AS device_time FROM versioned_params WHERE 1 AND object_id IN (0,1782) AND device_time < '2016-08-08 16:00:00.000' GROUP BY object_id, param_id;
|
+------+-------------+------------------+-------+--------------------+------------+---------+------+------+---------------------------------------+
|
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
|
+------+-------------+------------------+-------+--------------------+------------+---------+------+------+---------------------------------------+
|
| 1 | SIMPLE | versioned_params | range | PRIMARY,second_idx | second_idx | 15 | NULL | 664 | Using where; Using index for group-by |
|
+------+-------------+------------------+-------+--------------------+------------+---------+------+------+---------------------------------------+
|
1 row in set (0.00 sec)
|
|
MariaDB [test]> SELECT object_id, param_id, MAX(device_time) AS device_time FROM versioned_params WHERE 1 AND object_id IN (0,1782) AND device_time < '2016-08-08 16:00:00.000' GROUP BY object_id, param_id;
|
....
|
935 rows in set (0.02 sec)
|
|
10.0.26
|
MariaDB [test]> EXPLAIN SELECT object_id, param_id, MAX(device_time) AS device_time FROM versioned_params WHERE 1 AND object_id IN (0,1782) AND device_time < '2016-08-08 16:00:00.000' GROUP BY object_id, param_id;
|
+------+-------------+------------------+-------+--------------------+------------+---------+------+-------+--------------------------+
|
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
|
+------+-------------+------------------+-------+--------------------+------------+---------+------+-------+--------------------------+
|
| 1 | SIMPLE | versioned_params | range | PRIMARY,second_idx | second_idx | 4 | NULL | 36416 | Using where; Using index |
|
+------+-------------+------------------+-------+--------------------+------------+---------+------+-------+--------------------------+
|
1 row in set (0.13 sec)
|
|
MariaDB [test]> SELECT object_id, param_id, MAX(device_time) AS device_time FROM versioned_params WHERE 1 AND object_id IN (0,1782) AND device_time < '2016-08-08 16:00:00.000' GROUP BY object_id, param_id;
|
....
|
935 rows in set (0.04 sec)
|
MariaDB [test]> analyze table versioned_params;
|
+-----------------------+---------+----------+----------+
|
| Table | Op | Msg_type | Msg_text |
|
+-----------------------+---------+----------+----------+
|
| test.versioned_params | analyze | status | OK |
|
+-----------------------+---------+----------+----------+
|
1 row in set (8.54 sec)
|
MariaDB [test]> EXPLAIN SELECT object_id, param_id, MAX(device_time) AS device_time FROM versioned_params WHERE 1 AND object_id IN (0,1782) AND device_time < '2016-08-08 16:00:00.000' GROUP BY object_id, param_id;
|
+------+-------------+------------------+-------+--------------------+------------+---------+------+------+---------------------------------------+
|
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
|
+------+-------------+------------------+-------+--------------------+------------+---------+------+------+---------------------------------------+
|
| 1 | SIMPLE | versioned_params | range | PRIMARY,second_idx | second_idx | 15 | NULL | 2286 | Using where; Using index for group-by |
|
+------+-------------+------------------+-------+--------------------+------------+---------+------+------+---------------------------------------+
|
1 row in set (0.00 sec)
|
|
MariaDB [test]> SELECT object_id, param_id, MAX(device_time) AS device_time FROM versioned_params WHERE 1 AND object_id IN (0,1782) AND device_time < '2016-08-08 16:00:00.000' GROUP BY object_id, param_id;
|
|
935 rows in set (0.03 sec)
|
|
|
Well, after running ANALYZE for 5 hours it got back to the plan 'Using index for group-by' with following cardinalities:
| Table |
Non_unique |
Key_name |
Seq_in_index |
Column_name |
Collation |
Cardinality |
| versioned_params |
0 |
PRIMARY |
1 |
object_id |
A |
39798 |
| versioned_params |
0 |
PRIMARY |
2 |
time_id |
A |
378101114 |
| versioned_params |
0 |
PRIMARY |
3 |
param_id |
A |
4159112263 |
| versioned_params |
0 |
PRIMARY |
4 |
counter |
A |
24954673582 |
| versioned_params |
1 |
second_idx |
1 |
object_id |
A |
41533 |
| versioned_params |
1 |
second_idx |
2 |
param_id |
A |
1175720 |
| versioned_params |
1 |
second_idx |
3 |
device_time |
A |
24954673582 |
| versioned_params |
1 |
second_idx |
4 |
time_id |
A |
24954673582 |
So, I guess it's not a bug. Sorry for inconvenience
|
|
Yes, it's real pain that in order to have an optimal plan we have to run ANALYZE, which on big tables is barely possible, but I guess there isn't much that can be done about it right now.
|
|
As a suggestion: could SELECT DISTINCT on first column of the index automatically update index cardinality?
|
|
psergey, see the question above.
|