0

We have a lot of MariaDB's that we have recently moved to "Azure Database for MariaDB server". Most of the time it works OK, but we sometimes experience some snags with slow queries compared to running on our old servers. Let's just call our database "customerdb".

For example, we have two big tables, data_orders and data_orders_cardpayment, both quite big (data orders also contains an xml reprecentation of the order). For a customer that has about 900K rows in data_orders, the following query looks like this:

explain SELECT SQL_NO_CACHE 
   SUM(T0.GiftCard+T0.CreditNote+T0.Nettbank+T0.Depositum) AS Sum 
FROM DATA_ORDERS_CARDPAYMENT T0 
INNER JOIN DATA_ORDERS T1 ON T0.OrderId = T1.Id 
WHERE T1.IsTransferred = 0 
  AND T1.CountedId = -1 
  AND T1.InstanceCode = 'B';
+------+-------------+-------+-------------+----------------------------------------------+-------------------------+---------+--------------------+------+-------------------------------------------------------+
| id   | select_type | table | type        | possible_keys                                | key                     | key_len | ref                | rows | Extra                                                 |
+------+-------------+-------+-------------+----------------------------------------------+-------------------------+---------+--------------------+------+-------------------------------------------------------+
|    1 | SIMPLE      | T1    | index_merge | PRIMARY,CountedId,InstanceCode,IsTransferred | IsTransferred,CountedId | 1,4     | NULL               |  256 | Using intersect(IsTransferred,CountedId); Using where |
|    1 | SIMPLE      | T0    | ref         | OrderId                                      | OrderId                 | 4       | customerdb.T1.Id   |    1 |                                                       |
+------+-------------+-------+-------------+----------------------------------------------+-------------------------+---------+--------------------+------+-------------------------------------------------------+

So this only needs to check 256 rows? Good! Then I run this query at the start of the day, and it takes like this:

SELECT SQL_NO_CACHE
   SUM(T0.GiftCard+T0.CreditNote+T0.Nettbank+T0.Depositum) AS Sum 
FROM DATA_ORDERS_CARDPAYMENT T0 
INNER JOIN DATA_ORDERS T1 ON T0.OrderId = T1.Id 
WHERE T1.IsTransferred = 0 
  AND T1.CountedId = -1 
  AND T1.InstanceCode = 'B';
+------+
| Sum  |
+------+
|    0 |
+------+
1 row in set (1 min 38.283 sec)

So this took 1 minute and 38 seconds. Running it again, it takes only 0.119 seconds, 0.128 seconds, 0.106 seconds etc. I ran the same query on our old database server on the old database "customerdb_moved", there it took 2.68 seconds at the start of the day, and then 0.07 seconds afterwards (but that was a quite beefed up server).

So, why does it take forever the first time, and only the first time? I assume it for some unknown reason must load most of the table data from disk into memory, even though the indexes in theory should avoid this. Successive loads are always fast.

Can I avoid the initial loading from disk? If not, how do I speed up the initial disk access time in my Azure database? (BTW, at the moment, the pricing tier for the database server in Azure is 8 vCores, 80GB memory, 292 GB storage, 876 available IOPS, memory optimized.)

[Update] I found the main culprit at least. The explain statement somehow got things wrong. When running the following:

SELECT COUNT(*) 
FROM data_orders T1 
where T1.IsTransferred = 0 
  AND T1.CountedId = -1 
  AND T1.InstanceCode = 'B';

It actually returned about 5,5k rows, as there was some old lines that didn't have the T1.IsTransferred-flag set. I don't know why my explain returned 256 rows, and I still think the original query should take way less time than 1 minutes and 38 seconds initially for summing over these 5,5k rows on the first loop for the day. When setting the old lines to IsTransferred, the query today shows 5 rows for T1 in explain, while the count(*) FROM T1 shows 164 actual rows, and the query took about 3 seconds for the initial first time (still quite a lot for only a load of 164 rows) and then about 0.02 for the successive queries.

1

1 Answer 1

0

"Using intersect" usually implies that you need a composite index containing the columns mentioned.

When building a composite index, start with column(s) that are tested with = or IS NULL.

More on index building: Index Cookbook

As for the daily summary -- Build and maintain a Summary Table

If these don't help enough, there are more obscure things that could be going wrong; we need to see the actual code and SHOW CREATE TABLE. (Changing the column and table names is OK.)

As for MySQL vs MariaDB -- the Optimizers diverged at 5.6 / 10.0. Each has further improved (with only occasional regressions). You may have experienced a case where 10.x added an Optimization for which Azure does not yet have the equivalent.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.