数据库中进行表的链接查询比使用in的速度是要快的,怎样在程序中避免使用in?
postgresql提供了regexp_split_to_table这个函数,我们可以借助该函数避免使用in带来的问题
使用方法:
有表A,表A中有字段Id
使用in查询:select * from A where id in ( xxx,xxxx,xxxx)
替换后写法:select A.* from (select regexp_split_to_table('xxxx,xxx',',' ) as ids) as tt join A on tt.ids=A.id
分割方式随意,上面的替换的写法分割方式是“,”
附加:
1.创建表:CREATE TABLE gg( "Id" varchar(36));CREATE INDEX index_gg_id ON gg("Id"); CREATE TABLE ggu( "Id" varchar(36))
2.生成数据(golang代码)
func createdata(eng *xorm.Engine) {
c := make(chan int, 20)
for i := 0; i < 20; i++ {
eng.Exec(`insert into gg("Id") values('` + strings.UUID() + `')`)
c <- 1
}
i := 0
for {
select {
case <-c:
i++
default:
eng.Exec(`insert into gg("Id") values('` + strings.UUID() + `')`)
c <- 1
}
if i%10000 == 0 {
fmt.Println(time.Now())
}
if i > 1000000 {
break
}
}
}
用的uuid作为id
3.查询
func insearchspend(eng *xorm.Engine) {
ids := []string{
"752e92bc-9ac0-48e1-8dcc-e162acadfe15",
"ce16c8c9-4e24-4063-98b3-9b40ad312c2f",
"603bc795-92b1-4111-a7d5-3ece6861eb54",
}
result := make([]*gg, 0)
//ids = ids[0:2]
tm := time.Now()
err := eng.Table("gg").In(`"Id"`, ids).Find(&result)
if err != nil {
fmt.Println(err.Error())
}
fmt.Println(time.Now().UnixNano() - tm.UnixNano())
tm = time.Now()
err = eng.Sql(`SELECT "Id" FROM (SELECT regexp_split_to_table(?,',') AS tt) AS ids JOIN gg ON ids.tt=gg."Id"`, sysstring.Join(ids, ",")).Find(&result)
if err != nil {
fmt.Println(err.Error())
}
fmt.Println(time.Now().UnixNano() - tm.UnixNano())
tm = time.Now()
}
在本地测试性能差距10倍以上,测试数据量100万+ (上面是in,下面是regexp 单位:纳秒)
|