longblob字段的表,在并发查询的时候,未访问longblob字段,sql语句执行慢。

【 TiDB 使用环境】生产环境 /测试/ Poc
Poc
【 TiDB 版本】
v8.1.1
【复现路径】做过哪些操作出现的问题
【遇到的问题:问题现象及影响】
【资源配置】进入到 TiDB Dashboard -集群信息 (Cluster Info) -主机(Hosts) 截图此页面
【附件:截图/日志/监控】
复现步骤:

use test;
create table test.t3(id int primary key,name longblob);
insert into test.t3 values(1,REPEAT('A', 1048576)),(2,REPEAT('B', 1048576)),(3,REPEAT('C', 1048576))

使用 golang并发访问

package main

import (
        "database/sql"
        "fmt"

        _ "github.com/go-sql-driver/mysql"
)

func main() {
        db := getDB()
        defer db.Close()
        for i := 0; i < 400; i++ {
                go func() {
                        for {
                                rows, err := db.Query("SELECT `id` FROM t3 WHERE `id` = ? ", 1)
                                if err != nil {
                                        fmt.Printf("Query error: %v\n", err)
                                        return
                                }
                                defer rows.Close()
                                for rows.Next() {
                                        var id uint64
                                        if err := rows.Scan(&id); err != nil {
                                                fmt.Printf("Scan error: %v\n", err)
                                                continue
                                        }
                                }
                        }
                }()
        }
        select {}

}

func getDB() *sql.DB {
        db, err := sql.Open("mysql", "root:xxxxxx@tcp(192.168.76.12:4000)/test")
        if err != nil {
                panic(err)
        }
        db.SetConnMaxLifetime(-1)
        db.SetMaxOpenConns(300)
        db.SetMaxIdleConns(100)
        return db
}

会出现大于1s的查询。这个是否是正常现象。按道理没访问longblob 字段,应该不会出现超1s的慢查询

慢查询执行计划


| id          | estRows | estCost | actRows | task | access object               | execution info                                                                                                                                                                                                                                                                                                                                | operator info | memory | disk  |
| Point_Get_1 | 1.00    | 0.00    | 1       | root | table:t3, index:PRIMARY(id) | time:1.09s, loops:2, Get:{num_rpc:2, total_time:1.09s}, time_detail: {total_process_time: 680µs, total_wait_time: 12.8ms, total_kv_read_wall_time: 13.5ms, tikv_wall_time: 234.9ms}, scan_detail: {total_process_keys: 2, total_process_keys_size: 1048670, total_keys: 2, get_snapshot_time: 13.3µs, rocksdb: {block: {cache_hit_count: 4}}} |               | N/A    | N/A   |

point get 跑1s 不是预期的,可能是集群中存在性能瓶颈,可以先看看各组件负载和网络延迟有没有问题

集群不存在瓶颈,目前没上线。就这一条测试sql执行

那可能是你 longblob 字段比较大? tikv里面的数据存储是 key value 形式,取的话就是一整行一起取出来了,
从执行计划看这行的数据量也是挺大的

你可以试试没有longblob 的字段同样的并发查询的效率是啥样的

没有 longblob 字段的表,查询很快。
存在 longblob 字段的表,只查询id(不管是聚簇还是非聚簇)。都会存在超过1s的慢查询。按道理只走索引就可以,应该是很快的才对。

从执行计划的 key size 是都取出来了, 如果你字段比较大可以开以下 titan 试试看,可以有效提高读写性能
https://docs.pingcap.com/zh/tidb/stable/titan-configuration#开启-titan

1 个赞

https://github.com/pingcap/tidb/issues/52592
point_get 在设计上不支持列裁剪,有时或许比 cop 更慢,titan 或许是一个好办法

1 个赞