mysql迁移之后读取速度变慢_如何解决数据库迁移之后变慢的问题
阿里云關系型數據庫服務(Relational
Database Service,簡稱RDS)是一種即開即用、穩定可靠、可彈性伸縮的在線數據庫服務。具有多重安全防護措施和完善的性能監控體系,并提供專業的數據庫備份、恢復及優化方案,使您能專注于應用開發和業務發展。
使用阿里云關系數據庫RDS時,經常聽到很抱怨,為什么我的RDS 突然變慢了?相信不少客戶在使用RDS 中經常遇到的頭疼問題。像這樣情況的發生,可能是由于用戶操作不當而產生,為了重拾用戶對我們RDS的使用信心。 接下來我們通過真實案例來分析一下用戶在使用RDS 中變慢的原因:
案例一:
用戶從PGSQL遷移到RDS后,發現RDS變慢了。
問題描述:用戶的數據庫(pgsql)遷移到RDS(mysql)后,發現相同的一條sql 語句,數據量百萬級左右,在原來postgreSQL 中執行大概是0.015s,而在RDS 下直接運行是6分20秒左右,執行非常的慢,已經嚴重的影響用戶使用RDS的信心。而實際上,這個問題來自于異構數據庫的遷移,由于不同數據庫引擎使用的優化算法不同因此同一個SQL的性能表現會存在差異,能過以下操作我們可以進行分析并解決。
可能原因:為什么在用戶的數據庫上執行只需要0.015s,而到RDS 后變為了6分20s?根據經驗,很有可能是SQL 的執行計劃改變了,而導致執行時間劇增。
問題排查:通過explain 查看sql 的執行計劃,一步一步進行優化。
通過分析,可以從執行計劃上分析b 表做了一個全表掃描(執行計劃的最后一行),查看b 表中tid 并無索引,所以我們這里可以進行優化,來減少查詢過程中關聯的行數,從而達到優化:
我們可以看到執行計劃中的rows 已經從452變為了2(執行計劃的最后一行),
由于mysql 表關聯只有nest loop join 這種算法,所以我們可以估算一下這里的優化:
原始執行一:1055789*1*1*1*1*452
掃描的行數
新執行計劃二:1055789*1*1*1*1*2
掃描的行數
執行時間:
我們看到執行時間已經由原來的6分20秒下降到了10秒,我們繼續優化;
可以看到該sql 的結果集只有8行,但掃描的行數卻是非常之大的(1055789*1*1*1*1*2),在優化sql 的非常關鍵的一點就是優化sql 的執行路程,t=s/v;如果我們能夠優化S,那么速度肯定會一下子提上來;那么我們在看看sql 中最后的一句:
-> WHERE EXISTS
-> (SELECT 1 FROM xxxx_test5 b WHERE
a.tid = b.tid);
sql 查詢中是要查詢出每筆訂單的詳細信息而不得不關聯其他一些表,但是最后的一個exist 限定了我們最后結果的范圍,在看看xxxx_test5
這張表有多大:
mysql> SELECT COUNT(*) FROM xxxx_test5;
+----------+
| COUNT(*) |
+----------+
| 403 |
+----------+
1 ROW IN SET (0.00 sec)
mysql> SELECT COUNT(*) FROM xxxx_test5 b
,xxxx_test a WHERE
a.tid = b.tid ;
+----------+
| COUNT(*) |
+----------+
| 8 |
+----------+
1 ROW IN SET (0.42 sec)
兩張表關聯后只有8行記錄,如果我們將訂單表xxxx_test 和限定表先做關聯,在和其他的一些訂單信息表做連接,將會極大減小關聯的行數;在進一步改寫sql:
分析執行計劃,我們發現限定表xxxx_test5做了驅動表,驅動表的變化才是導致問題的最根本原因,掃描的行數:452*1*1*1*1; 這個時候sql 的執行速度將非常快:
Mysql-->;
SELECT a.oi.............
........省去結果
8 ROWS IN SET (0.13 sec)
總結:由于環境遷移,導致sql執行計劃改變,這就是RDS變慢的最終原因。
案例二:
用戶使用RDS(mssql),經常出現連接超時報錯。
問題描述:?使用mssql rds 時不時報錯如下,詢問是否是連接超過限制導致的?
A network-related orinstance-specific error
occurred while establishing a connection toSQL Server. The server was not found
or was not accessible. Verifythat the instance name is correct and that SQL
Server is configured toallow remote connections. (provider: SQL Network
Interfaces, error:26 – Error Locating
Server/Instance Specified)
可能原因:可能用戶的應用程序設計的不是很好,導致數據庫鎖征用較多;或由于沒有建立適當的索引,導致全表掃描,造成數據庫等待;
問題排查:通過查看數據庫的監控指標,發現在某個時間段有大量的全表掃描,同時數據庫的鎖爭超時,會話數明顯增加。
可以看到在15:00的時候有大量的全表掃描,出現了較多的鎖超時的情況,同時這個時候也有大量的會話在數據庫中,而這個時間恰好也是用戶報出錯誤的時間,在進一步排查,用戶的SQL,通過查看mssql 內部的一些視圖,來找到對應消耗資源top 5的sql,發現用戶頻繁的查詢一個視圖,在視圖中有多表連接,但在這些表連接中的字段上沒有添加索引,導致了全表掃描,用戶視圖如下:
CREATE VIEW [dbo].[Vi_xxx]
AS
SELECT ..........
..........
FROM dbo.xxxx_test6 INNER JOIN
dbo.xxxx_test1 ON dbo.xxxx_test5.docID =
dbo.xxxx_test1.docID
INNER JOIN
dbo.xxxx_test2 ON dbo.xxxx_test5.typeID =
dbo.xxxx_test2.typeID
INNER JOIN
dbo.xxxx_test3 ON dbo.xxxx_test5.docID =
dbo.xxxx_test3.docID
INNER JOIN
dbo.xxxx_test4 ON dbo.xxxx_test5.categoryID
=
dbo.xxxx_test4.categoryID
WHERE (dbo.xxxx_test5.isDelete = 0)
通過查看執行計劃,發現表上面很多的關聯字段沒有建立索引,導致全表掃描執行計劃如下(有很多的table scan):
總結:用戶頻繁的查詢一個視圖,而該視圖中表的關聯字段上沒有索引,導致了大量的全表掃描,累積了大量的會話數,造成數據庫性能的下降,應用與數據庫之間出現連接錯誤。
案例三:
隱式轉換導致全表掃描
問題描述:用戶網站打開緩慢,質疑RDS 性能不好。
可能原因:用戶的數據存放在RDS 中,網站訪問數據庫的時間較長,大多web應用程序設計,SQL沒有優化或索引建立的不好導致;
問題排查:通過查看數據庫的慢日志,發現大量的慢sql,執行時間超過了2S。
UPDATE USER SET xx=xx+N.N WHERE
account=130000870343 LIMIT 10
SELECT * FROM USER WHERE
account=13056870 LIMIT 10
懷疑在user 表上是否建立索引:
CREATE TABLE `user` (
`id` smallint(5) unsigned NOT NULL
AUTO_INCREMENT,
`account` char(11) NOT NULL COMMENT ‘???’,
…………………….
…………………….
PRIMARY KEY (`id`),
UNIQUE KEY `username` (`account`),
…………………….
) ENGINE=InnoDB CHARSET=utf8 ;
查看執行計劃,居然查詢使用了全表掃描:
db@3027 16:55:06>explain
select * from user where
account=13056870343;
+—-+————-+——–+——+—————+——+———+——+——+————-+
| id | select_type | table | type |
possible_keys | key | key_len | ref |
rows | Extra |
+—-+————-+——–+——+—————+——+———+——+——+————-+
| 1 | SIMPLE | t_user | ALL | username |
NULL | NULL | NULL | 799 |
Using where |
+—-+————-+——–+——+—————+——+———+——+——+————-+
1 row in set (0.00 sec)
為什么這里會是全表掃描?account 上不是已經建立索引來嗎?仔細一看,account 定義為了字符串,而傳入的條件為數字,我們知道數字的精度是比字符串高的,所以這里做了隱士轉換:
to_number(account)=13056870343
(to_number 為將字符串轉換為數字),這樣即使account 上有索引,也沒法使用了,因此我們將傳入的數字改為字符串:
db@3027 16:55:13>EXPLAIN SELECT * FROM
USER WHERE
account='13056870343';
+----+-------------+--------+-------+---------------+----------+------
| id | select_type | TABLE | TYPE |
possible_keys | KEY |
key_len | REF | ROWS | Extra |
+----+-------------+--------+-------+---------------+----------+------
| 1 | SIMPLE | t_user | const | username |
username | 33
| const | 1 | |
+----+-------------+--------+-------+---------------+----------+------
1 ROW IN SET (0.00 sec)
可以看到數據已經能夠索引到索引username 了。
總結:由于用戶在設計表結構的時候字段定義使用了字符串,而傳入的條件卻傳入了數字造成了隱士轉換,這是數據庫應用中經常出現的典型問題; RDS足夠穩定,但不論在怎么強的數據庫,也經不起劣質SQL的挑戰,優化sql是長期的一項優化措施。
從上面的三個案例,我們可以總結一下,用戶在使用RDS
的時候,發現數據庫執行sql 超時,性能較差,連接超時等等這些問題,大多數情況下,是由于應用程序的設計,sql 沒有優化,或者索引建立的不好而導致;除非實例不可用(主機down 掉,實例服務停掉,實例由于空間太大而被鎖定)而導致用戶應用不可用(實例的故障RDS 會有監控報警)。
總結
以上是生活随笔為你收集整理的mysql迁移之后读取速度变慢_如何解决数据库迁移之后变慢的问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: c语言局部变量存在什么区_C语言程序设计
- 下一篇: 设置mysql整形_mysql 整型字