MariaDB 升级 10.3 至 10.9,索引、eq_range_index_dive_limit 和 EXPLAIN

问题描述 投票:0回答:1

我目前正在将 MariadDB 服务器从 10.3 (10.3.38-MariaDB-0ubuntu0.20.04.1) 升级到 10.9 (10.9.3-MariaDB-1:10.9.3+maria~ubu2004-log)

我已经在本地运行 10.9 版本一段时间,为将其放入生产环境做准备。当我一直在努力优化一些较大的查询时,我注意到在本地生产中的某些情况下没有使用索引,但实际上是这样。

据我了解,这是这些版本号和一些设置之间的变化,以及引擎试图“更智能”地了解使用优化的成本与仅继续进行不使用索引的表扫描的成本。很多谷歌搜索已经产生了关于以下内容的帖子:

eq_range_index_dive_limit, use_stat_tables, sort_buffer_size

我可能有点守旧,但是当我运行 EXPLAIN 时,我看到可能的键,但没有使用,这表明存在某种问题。假设 ANALYZE TABLE 的任何变体都没有导致索引开始被使用。升级后,我在测试生产机器上观察到相同的行为,因为索引使用情况与我在本地看到的内容重复。

我关心的一篇文章是这样一种情况:查询的实际结果没有被引擎很好地“测量”,强制索引是唯一的选择。这就是我担心的 - 在生产负载下将 10.9 放入我的生产环境(这对我来说很难进行可靠的模拟)并看到速度下降。

我该怎么办:

  1. 相信版本号之间的变化,祈祷放弃索引的使用会表现更好,或者
  2. 通过解释运行我的所有查询,并开始在整个地方强制索引(在我意识到发生了什么之前我就这样做了),因为
  3. 我什至不确定如何衡量什么更好,让引擎决定不使用索引,或者我强制使用索引。

我想要一些关于你们中的一些人如何处理这个问题的反馈,或者甚至是关于调整以获得更多索引使用的建议?如果使用索引不如表扫描,我真的会遇到速度变慢的情况吗?

FWIW,我已经上下调整了上面这三个服务器选项的设置值,并且没有任何改变该简单 SELECT 语句的索引使用...

感谢您的输入,上下文如下。

MariaDB [pweb]> EXPLAIN extended select * from `accounting_transactions` where `accounting_transactions`.`cr_account` = 'f7d78ef5-ca59-44d1-9d67-70a83960f473' \G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: accounting_transactions
         type: ALL
possible_keys: accounting_transactions_cr_account_index
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 532030
     filtered: 35.63
        Extra: Using where
1 row in set, 1 warning (0.002 sec)
MariaDB [pweb]> EXPLAIN extended select * from `accounting_transactions` force index (accounting_transactions_cr_account_index ) where `accounting_transactions`.`cr_account` = 'f7d78ef5-ca59-44d1-9d67-70a83960f473'\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: accounting_transactions
         type: ref
possible_keys: accounting_transactions_cr_account_index
          key: accounting_transactions_cr_account_index
      key_len: 144
          ref: const
         rows: 189558
     filtered: 100.00
        Extra: Using index condition
1 row in set, 1 warning (0.001 sec)
MariaDB [pweb]> SELECT VERSION();
+-------------------------------------------+
| VERSION()                                 |
+-------------------------------------------+
| 10.9.3-MariaDB-1:10.9.3+maria~ubu2004-log |
+-------------------------------------------+
1 row in set (0.001 sec)
MariaDB [pweb]> show create table accounting_transactions \G
*************************** 1. row ***************************
       Table: accounting_transactions
Create Table: CREATE TABLE `accounting_transactions` (
  `id` char(36) COLLATE utf8mb4_unicode_ci NOT NULL,
  `event_id` char(36) COLLATE utf8mb4_unicode_ci NOT NULL,
  `amount` decimal(10,2) NOT NULL,
  `dr_account` char(36) COLLATE utf8mb4_unicode_ci NOT NULL,
  `cr_account` char(36) COLLATE utf8mb4_unicode_ci NOT NULL,
  `created_at` timestamp NULL DEFAULT NULL,
  `updated_at` timestamp NULL DEFAULT NULL,
  `deleted_at` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `accounting_transactions_event_id_index` (`event_id`),
  KEY `accounting_transactions_dr_account_index` (`dr_account`),
  KEY `accounting_transactions_cr_account_index` (`cr_account`),
  CONSTRAINT `accounting_transactions_cr_account_foreign` FOREIGN KEY (`cr_account`) REFERENCES `accounting_accounts` (`id`),
  CONSTRAINT `accounting_transactions_dr_account_foreign` FOREIGN KEY (`dr_account`) REFERENCES `accounting_accounts` (`id`),
  CONSTRAINT `accounting_transactions_event_id_foreign` FOREIGN KEY (`event_id`) REFERENCES `accounting_events` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
1 row in set (0.002 sec)
MariaDB [pweb]> SHOW variables LIKE '%query_cache%';
+------------------------------+----------+
| Variable_name                | Value    |
+------------------------------+----------+
| have_query_cache             | YES      |
| query_cache_limit            | 1048576  |
| query_cache_min_res_unit     | 4096     |
| query_cache_size             | 16777216 |
| query_cache_strip_comments   | OFF      |
| query_cache_type             | OFF      |
| query_cache_wlock_invalidate | OFF      |
+------------------------------+----------+
7 rows in set (0.002 sec)
MariaDB [pweb]> SHOW variables where Variable_name in ('eq_range_index_dive_limit', 'use_stat_tables', 'sort_buffer_size')\G
*************************** 1. row ***************************
Variable_name: eq_range_index_dive_limit
        Value: 100000000
*************************** 2. row ***************************
Variable_name: sort_buffer_size
        Value: 209715200
*************************** 3. row ***************************
Variable_name: use_stat_tables
        Value: NEVER
3 rows in set (0.002 sec)

在某些基于实际查询时间的情况下 - 我注意到在不使用索引的情况下返回速度更快,我不得不说这是非常令人惊讶的。这支持选项1吗?

mariadb explain database-indexes
1个回答
0
投票

91785/538368 -- 使用了表的 17%。

当获取大量表时,进行表扫描通常会更快。当使用索引时,需要在索引的BTree和数据的BTree之间来回跳动。这种弹跳

可能比简单地对数据进行线性扫描(丢弃 83% 的行)需要更长的时间。 唉,优化器没有足够的统计数据来说明哪种方式更快。

在这种情况下,结果集的大小可能太大,无法放入查询缓存。因此,即使它已打开,尝试使用 QC 也可能会导致额外的开销。

您可以做的一件事就是缩小

CHAR(36)

弦。要么使用 UUID 数据类型,要么至少将它们打包为

BINARY(16)

。我的 
UUIDs
博客甚至在数据类型存在之前就讨论了这一点。 客户端到底要如何处理 91785 行?另一个提示:如果客户没有使用所有列,请仅拼出必要的列,而不是使用 SELECT *

© www.soinside.com 2019 - 2024. All rights reserved.