英文:
Slow queries for specific table after upgrading MariaDB 10.3 to 10.11
问题
我最近将我们的数据库服务器从MariaDB 10.3升级到了10.11,其中一个表格的查询时间明显比10.3慢。以下这个简单的查询在10.11上需要大约10秒才能完成,而在10.3上则瞬间完成。这个表格大约有67,000条记录,对于在过滤器中没有使用索引的查询都运行得很慢。我不明白为什么升级只会导致一个表格的查询变慢。我们有其他表格有超过100,000条记录,可以瞬间完成表格扫描。这个表格可以通过许多列进行搜索,所以我不想不得不在所有列上都加索引,特别是因为在升级前这不是一个问题。
SELECT * FROM student_repository WHERE LAST_NAME = "DOE"
CREATE TABLE `student_repository` (
`ID` bigint(20) NOT NULL AUTO_INCREMENT,
`FIRST_NAME` varchar(255) DEFAULT NULL,
`LAST_NAME` varchar(255) DEFAULT NULL,
`AID_YEAR` int(11) DEFAULT NULL,
`TRANSACTION_NUMBER` int(11) DEFAULT NULL,
`ISIR_LINE` varchar(15000) DEFAULT NULL,
`ISIR_HEADER_ID` bigint(20) DEFAULT NULL,
`SESSION_ID` bigint(20) NOT NULL,
`SSN_LAST_FOUR` varchar(4) DEFAULT NULL,
`ED_HASH_TRANSFER` varchar(255) DEFAULT NULL,
`ED_HASH_CURRENT` varchar(255) DEFAULT NULL,
`ED_HASH_ORIGINAL` varchar(255) DEFAULT NULL,
`EXPORTED_BY_USER_ID` varchar(255) DEFAULT NULL,
`EXPORTED_DATE` datetime DEFAULT NULL,
`SID` varchar(255) DEFAULT NULL,
`SCHOOL_CODE` varchar(255) DEFAULT NULL,
`STATUS` varchar(255) DEFAULT NULL,
`STUDENT_ID_FK` bigint(20) DEFAULT NULL,
`EOP` bit(1) DEFAULT b'0',
`ED_HASH` varchar(255) DEFAULT NULL,
PRIMARY KEY (`ID`),
KEY `idx_student_repository_ED_HASH_ORIGINAL` (`ED_HASH_ORIGINAL`),
KEY `idx_student_repository_STUDENT_ID_FK` (`STUDENT_ID_FK`),
KEY `idx_student_repository_ED_HASH_CURRENT` (`ED_HASH_CURRENT`),
KEY `idx_student_repository_ED_HASH_TRANSFER` (`ED_HASH_TRANSFER`)
) ENGINE=InnoDB AUTO_INCREMENT=134634 DEFAULT CHARSET=latin1
COLLATE=latin1_swedish_ci;
我已经尝试运行ANALYZE命令来更新表格的统计信息,但没有帮助。
我在查找版本间是否有任何更改会导致这种性能下降的服务器选项方面感到困难。
执行计划之间存在一些差异,但我不确定是什么原因导致的。
10.3版本执行计划
10.11版本执行计划
10.3版本解释计划
10.11版本解释计划
我找到的唯一其他差异是我们的10.3版本进程列表中有InnoDB清理线程,而在10.11中却没有。我在想是否这些缺失导致了性能问题,但我无法弄清楚如何启动它们。
10.3版本进程列表
英文:
I recently upgraded our db servers from MariaDB 10.3 to 10.11 and one of our tables takes significantly longer to query than it did on 10.3. The following simple query takes about 10 seconds to query on 10.11, and it runs instantly on 10.3. The table has about 67,000 records and it runs slow on any query that isn't using an index in the filter. I'm confused why the upgrade would only cause one table to query slowly. We have other tables with over 100,000 records that can do table scans instantly. This table can be searched by many columns, so I'd rather not have to put indexes on all the columns especially since this wasn't a problem pre-upgrade.
SELECT * FROM student_repository WHERE LAST_NAME = "DOE"
CREATE TABLE `student_repository` (
`ID` bigint(20) NOT NULL AUTO_INCREMENT,
`FIRST_NAME` varchar(255) DEFAULT NULL,
`LAST_NAME` varchar(255) DEFAULT NULL,
`AID_YEAR` int(11) DEFAULT NULL,
`TRANSACTION_NUMBER` int(11) DEFAULT NULL,
`ISIR_LINE` varchar(15000) DEFAULT NULL,
`ISIR_HEADER_ID` bigint(20) DEFAULT NULL,
`SESSION_ID` bigint(20) NOT NULL,
`SSN_LAST_FOUR` varchar(4) DEFAULT NULL,
`ED_HASH_TRANSFER` varchar(255) DEFAULT NULL,
`ED_HASH_CURRENT` varchar(255) DEFAULT NULL,
`ED_HASH_ORIGINAL` varchar(255) DEFAULT NULL,
`EXPORTED_BY_USER_ID` varchar(255) DEFAULT NULL,
`EXPORTED_DATE` datetime DEFAULT NULL,
`SID` varchar(255) DEFAULT NULL,
`SCHOOL_CODE` varchar(255) DEFAULT NULL,
`STATUS` varchar(255) DEFAULT NULL,
`STUDENT_ID_FK` bigint(20) DEFAULT NULL,
`EOP` bit(1) DEFAULT b'0',
`ED_HASH` varchar(255) DEFAULT NULL,
PRIMARY KEY (`ID`),
KEY `idx_student_repository_ED_HASH_ORIGINAL` (`ED_HASH_ORIGINAL`),
KEY `idx_student_repository_STUDENT_ID_FK` (`STUDENT_ID_FK`),
KEY `idx_student_repository_ED_HASH_CURRENT` (`ED_HASH_CURRENT`),
KEY `idx_student_repository_ED_HASH_TRANSFER` (`ED_HASH_TRANSFER`)
) ENGINE=InnoDB AUTO_INCREMENT=134634 DEFAULT CHARSET=latin1
COLLATE=latin1_swedish_ci;
I've tried to run ANALYZE on the table to get the statistics updated and that didn't help.
I'm struggling to find any server options that changed between versions that would cause this kind of slow down.
There are some differences between the execution plan, but I'm not sure what is causing it.
10.3 Execution Plan
10.11 Execution Plan
10.3 Explain
10.11 Explain
The only other differences I've found is that our 10.3 processlist has InnoDB purge threads and they are missing in 10.11. I'm wondering if those missing are causing a performance issue, but I can't figure out how to start them.
10.3 Processlist
答案1
得分: 0
大表的表扫描不是瞬间完成的。它们会占用数据库服务器的CPU和IO操作。对于已缓存的行来说可能很快,但并非瞬间完成。
你展示的查询需要这个索引以保证效率。
CREATE KEY idx_student_repository_LAST_NAME
ON student_repository(LAST_NAME );
很难说为什么在你的旧服务器上没有这个索引也很有效。这让人感到惊讶。可能旧服务器的 query_cache_type 变量被设置为开启(1),并且你的快速查询在某种程度上满足于缓存中(因为它之前运行得很慢)。新版本将其设置为关闭(0),有充分的理由。
专业提示 根据应用程序中哪些查询较慢来决定你需要哪些索引。不要“在所有列上放置索引”。随着应用程序的增长,表通常需要新的索引,但很难预测在应用程序增长之前需要哪些索引。定期检查应用程序的SQL性能并确定随着表的增长是否需要新索引是标准操作流程。
查看这个链接 https://use-the-index-luke.com/。
英文:
Table scans for large tables aren't instantaneous. They take CPU and IO operations on your database server. They may be fast, especially for cached rows, but instantaneous they are not.
The query you showed us needs this index to be efficient.
CREATE KEY idx_student_repository_LAST_NAME
ON student_repository(LAST_NAME );
It's hard to say why this was efficient on your old server without this index. That's surprising. It's possible the old server had the query_cache_type variable set to ON (1) and your fast query was somehow satisfied from the cache (because it already ran slowly). Newer versions have it set to OFF (0), for good reasons.
Pro tip Decide which indexes you need based on which queries are slow in your application. Don't "put indexes on all the columns". As apps grow their tables often need new indexes, and it's really hard to predict what indexes they'll need before app growth. It's standard operating procedure to revisit your app's SQL performance every month or so, and determine whether new indexes are needed as tables grow.
Check this out https://use-the-index-luke.com/
答案2
得分: 0
问题出在表格 ISIR_LINE
的大列上,它的 varchar(15000) 类型。在10.3版本中,如果在select语句中返回该列,查询速度很慢,但如果将其从select语句中删除,查询会运行得很快。似乎在10.11版本中,即使在select语句中不包含该列,它仍会分配内存给进程,导致速度变慢。这似乎只在进行全表扫描时才会发生,因此我将该列移到了自己的表格中,并使用外键连接回原始表格并对其进行了优化。现在,在主表格上进行全表扫描速度很快。
我们发现,如果表格中的列的最大字符长度为3,000与2,500相比,性能会大幅下降。因此,如果表格中的某列长度超过2,500,您应该尝试在您筛选的列上建立索引,如果可能的话,降低列的最大长度,或者将其移到自己的表格中,并使用外键将其连接到主表格中。
英文:
It turns out the issue was the large column on the table ISIR_LINE
varchar(15000). In 10.3 queries were slow if you returned that column in a select, but if you removed it from the select it would run quick. Seems like in 10.11 even if you leave that column off of the select it will still allocate that memory to the process, causing it to be slower still. This seems to only be the case if it is a full table scan, so I moved the column out into its own table with a FK back to the original and optimized the table. Now a full table scan runs quickly on the main table.
We saw a large decrease in performance if a table had a column with a max character length of 3,000 vs 2,500. So, if a table has a column of length over 2,500 you should try putting an index on the columns you are filtering by, lowering the max length of the column if you can, or moving it to it's own table with a FK connecting it to the main table.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论