LBS发现好友

Wesley13
• 阅读 645

近两年、手机应用,莫过于微信、陌陌之类最受欢迎;但实现原理,分享文章甚少。
故,提出两种方案,供分享;不对之处,敬请留言学习。

目标

解决大型应用(微信、陌陌级别)中,用户经纬度在不断更新,用户查找频繁的问题。(每分钟1000W级)

=================================================================================================
方案A

本方案前,请先阅读 http://www.wubiao.info/372

由上文,简单可得;
1、仅需每分钟将用户的经纬度,上报到数据库;
2、然后每次用户查找附近好友时,通过 LIKE ‘wm3yr3%’,即可获取

缺点:稍有一定数据量,对数据库的鸭梨可想而知

=================================================================================================
方案B

策略

假象把中国分成,若干个一平方公里的单元格,
1、用户位置的变更,理解为一个单元格移动到另外一个单元格(或者不移动)
2、用户查找附近,理解为查找,自己所在方块的的所有人

数据结构

1、用户基本信息 纬度、经度、GeoHash值(经纬度,仅用于后期距离计算)
2、单元格 集合(用户1,用户2,…)

存储工具

1、redis string(key->value) 结构,存储用户基本信息
2、redis set(集合) 结构,以GeoHash值,前6位作为key(约表示一平方千米),存储单元格的用户群

算法流程

1、更新用户信息,先删除用户原所在集合,再更新当前用户信息,最后更新当前用户所在集合
2、查找附近,直接查找,所在单元格集合所有用户ID

具体实现

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

<?php

/**

* LBS核心类

*

* [@author](http://my.oschina.net/arthor) name <simplephp@163.com>

* [@site](http://my.oschina.net/u/859132) http: //www .wubiao.info

*/

include_once( 'geohash.class.php' );

class lbs

{

// 索引长度 6位

protected $index_len = 6;

protected $redis;

protected $geohash;

public function __construct()

{

//redis

$this->redis = new Redis();

$this->redis->pconnect( '127.0.0.1' , '6379' );

//geohash

$this->geohash = new Geohash();

}

/**

* 更新用户信息

*

* @param mixed $latitude 纬度

* @param mixed $longitude 经度

*/

public function upinfo($user_id,$latitude,$longitude)

{

// 原数据处理

// 获取原Geohash

$o_hashdata = $this->redis->hGet($user_id, 'geo' );

if (!empty($o_hashdata))

{

// 原索引

$o_index_key = substr($o_hashdata, 0, $this->index_len);

// 删除

$this->redis->sRem($o_index_key,$user_id);

}

// 新数据处理

// 纬度

$this->redis->hSet($user_id, 'la' ,$latitude);

// 经度

$this->redis->hSet($user_id, 'lo' ,$longitude);

//Geohash

$hashdata = $this->geohash->encode($latitude,$longitude);

$this->redis->hSet($user_id, 'geo' ,$hashdata);

// 索引

$index_key = substr($hashdata, 0, $this->index_len);

// 存入

$this->redis->sAdd($index_key,$user_id);

return true ;

}

/**

* 获取附近用户

*

* @param mixed $latitude 纬度

* @param mixed $longitude 经度

*/

public function serach($latitude,$longitude)

{

//Geohash

$hashdata = $this->geohash->encode($latitude,$longitude);

// 索引

$index_key = substr($hashdata, 0, $this->index_len);

// 取得

$user_id_array = $this->redis->sMembers($index_key);

return $user_id_array;

}

}

?>

性能测试

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

<?php

/**

* 模拟数据上报

*

* [@author](http://my.oschina.net/arthor) name <simplephp@163.com>

* [@site](http://my.oschina.net/u/859132) http: //www .wubiao.info

*/

include_once( 'lbs.class.php' );

$b_time = microtime( true );

$n = 0;

while (1)

{

//user_id 1~1000000

$user_id = rand(1,1000000);

//latitude 30.59773~30.726786

$rand_latitude = rand(30597730,30726786);

$latitude = $rand_latitude /1000000 ;

//longitude 103.983192 ~104.16069

$rand_longitude = rand(103983192,104160690);

$longitude = $rand_longitude /1000000 ;

$lbs = new lbs();

$lbs->upinfo($user_id,$latitude,$longitude);

$n++;

mylog($n);

$e_time = microtime( true );

if (($e_time-$b_time)>=60)

{

exit ;

}

}

function mylog($content)

{

file_put_contents( 'upinfo.log' ,$content. "\r\n" ,FILE_APPEND);

}

?>

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

<?php

/**

* 模拟查找附近

*

* [@author](http://my.oschina.net/arthor) name <simplephp@163.com>

* [@site](http://my.oschina.net/u/859132) http: //www .wubiao.info

*/

include_once( 'lbs.class.php' );

$b_time = microtime( true );

$n = 0;

while (1)

{

//latitude 30.59773~30.726786

$rand_latitude = rand(30597730,30726786);

$latitude = $rand_latitude /1000000 ;

//longitude 103.983192 ~104.16069

$rand_longitude = rand(103983192,104160690);

$longitude = $rand_longitude /1000000 ;

$lbs = new lbs();

$re = $lbs->serach($latitude,$longitude);

$n++;

mylog($n);

$e_time = microtime( true );

if (($e_time-$b_time)>=60)

{

exit ;

}

}

function mylog($content)

{

file_put_contents( 'search.log' ,$content. "\r\n" ,FILE_APPEND);

}

?>

测试环境

虚拟机,内存256M,主频2.93GHz

性能结果

模拟了100W活跃用户行为,不断更新,不断查找附近好友

//60 seconds insert
88544

//60 seconds search
117660

//成都 100W人,数据占用内存
11.97M

总结

从测试结果来看,完全能满足,微信、陌陌之类的性能要求;

尚可改进之处:

1、Geohash,可写成PHP C扩展;或者其他Geohash实现方式
2、Redis,内存消耗较大,可考虑redis集群方案
3、本文仅查出本单元格用户,提高精度,可查出周围八个单元个,求交集
4、求出结果,如需按照由远到近排序;读出Redis经纬度,利用距离公式排序方可。(可参照上一篇文字)

附redis安装方法
=================================================================================================
//redis

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

wget http: //redis .googlecode.com /files/redis-2 .4.14. tar .gz

make

make install

// 配置

cp redis.conf /etc/

vi /etc/redis .conf

#后台

daemonize yes

#日志

logfile /dev/null

#存储

dir ./

// 小内存,内核参数

echo 1 > /proc/sys/vm/overcommit_memory

// 防火墙

vi /etc/sysconfig/iptables

-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 6379 -j ACCEPT

service iptables restart

// 启动

redis-server /etc/redis .conf

// 测试

redis-cli set foo bar

OK

redis-cli get foo

bar

=================================================================================================
//php redis 扩展

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

// 源码

http: //code .google.com /p/phpredis/

// 手册

http: //redis .readthedocs.org /en/latest/

// 安装

/opt/server/php/bin/phpize

. /configure --with-php-config= /opt/server/php/bin/php-config

make

make install

// 配置

vi php.ini

[redis]

extension = redis.so

分类: Database架构算法 标签: geohashredis微信,陌陌,LBS

查找附近的xxx 球面距离以及Geohash方案探讨

2012年6月14日 simple 7 条评论

随着移动终端的普及,很多应用都基于LBS功能,附近的某某(餐馆、银行、妹纸等等)。

基础数据中,一般保存了目标位置的经纬度;利用用户提供的经纬度,进行对比,从而获得是否在附近。

目标:
查找附近的XXX,由近到远返回结果,且结果中有与目标点的距离。

针对查找附近的XXX,提出两个方案,如下:

一、方案A:
=================================================================================================

抽象为球面两点距离的计算,即已知道球面上两点的经纬度;
点(纬度,经度),A($radLat1,$radLng1)、B($radLat2,$radLng2);

优点:通俗易懂,部署简单便捷

缺点:每次都会查询数据库,性能堪忧

1、推导

通过余弦定理以及弧度计算方法,最终推导出来的算式A为:

1

$s = acos(cos($radLat1)*cos($radLat2)*cos($radLng1-$radLng2)+sin($radLat1)*sin($radLat2))*$R;

目前网上大多使用Google公开的距离计算公司,推导算式B为:

1

$s = 2*asin(sqrt(pow(sin(($radLat1-$radLat2) /2 ),2)+cos($radLat1)*cos($radLat2)*pow(sin(($radLng1-$radLng2) /2 ),2)))*$R;

其中 :
$radLat1、$radLng1,$radLat2,$radLng2 为弧度

$R 为地球半径

2、通过测试两种算法,结果相同且都正确,但通过PHP代码测试,两点间距离,10W次性能对比,自行推导版本计算时长算式B较优,如下:

//算式A
0.56368780136108float(431)
0.57460689544678float(431)
0.59051203727722float(431)

//算式B
0.47404885292053float(431)
0.47808718681335float(431)
0.47946381568909float(431)

3、所以采用数学方法推导出的公式:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

<?php

// 根据经纬度计算距离 其中A($lat1,$lng1)、B($lat2,$lng2)

public static function getDistance($lat1,$lng1,$lat2,$lng2)

{

// 地球半径

$R = 6378137;

// 将角度转为狐度

$radLat1 = deg2rad($lat1);

$radLat2 = deg2rad($lat2);

$radLng1 = deg2rad($lng1);

$radLng2 = deg2rad($lng2);

// 结果

$s = acos(cos($radLat1)*cos($radLat2)*cos($radLng1-$radLng2)+sin($radLat1)*sin($radLat2))*$R;

// 精度

$s = round($s* 10000) /10000 ;

return  round($s);

}

?>

4、在实际应用中,需要从数据库中遍历取出符合条件,以及排序等操作,

将所有数据取出,然后通过PHP循环对比,筛选符合条件结果,显然性能低下;所以我们利用下Mysql存储函数来解决这个问题吧。

4.1、创建Mysql存储函数,并对经纬度字段建立索引

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

DELIMITER $$

CREATE DEFINER=`root`@`%` FUNCTION `GETDISTANCE`(lat1 DOUBLE, lng1 DOUBLE, lat2 DOUBLE, lng2 DOUBLE) RETURNS double

READS SQL DATA

DETERMINISTIC

BEGIN

DECLARE RAD DOUBLE;

DECLARE EARTH_RADIUS DOUBLE DEFAULT 6378137;

DECLARE radLat1 DOUBLE;

DECLARE radLat2 DOUBLE;

DECLARE radLng1 DOUBLE;

DECLARE radLng2 DOUBLE;

DECLARE s DOUBLE;

SET RAD = PI() / 180.0;

SET radLat1 = lat1 * RAD;

SET radLat2 = lat2 * RAD;

SET radLng1 = lng1 * RAD;

SET radLng2 = lng2 * RAD;

SET s = ACOS(COS(radLat1)*COS(radLat2)*COS(radLng1-radLng2)+SIN(radLat1)*SIN(radLat2))*EARTH_RADIUS;

SET s = ROUND(s * 10000) / 10000;

RETURN s;

END$$

DELIMITER ;

4.2、查询SQL

通过SQL,可设置距离以及排序;可搜索出符合条件的信息,以及有一个较好的排序

1

SELECT *,latitude,longitude,GETDISTANCE(latitude,longitude,30.663262,104.071619) AS distance FROM  mb_shop_ext where 1 HAVING distance<1000 ORDER BY distance ASC LIMIT 0,10

二、方案B
=================================================================================================

Geohash算法;geohash是一种地址编码,它能把二维的经纬度编码成一维的字符串。
比如,成都永丰立交的编码是wm3yr31d2524

优点:

1、利用一个字段,即可存储经纬度;搜索时,只需一条索引,效率较高
2、编码的前缀可以表示更大的区域,查找附近的,非常方便。 SQL中,LIKE ‘wm3yr3%’,即可查询附近的所有地点。
3、通过编码精度可模糊坐标、隐私保护等。

缺点: 距离和排序需二次运算(筛选结果中运行,其实挺快)

1、geohash的编码算法

成都永丰立交经纬度(30.63578,104.031601)

1.1、纬度范围(-90, 90)平分成两个区间(-90, 0)、(0, 90), 如果目标纬度位于前一个区间,则编码为0,否则编码为1。
由于30.625265属于(0, 90),所以取编码为1。
然后再将(0, 90)分成 (0, 45), (45, 90)两个区间,而39.92324位于(0, 45),所以编码为0,
然后再将(0, 45)分成 (0, 22.5), (22.5, 45)两个区间,而39.92324位于(22.5, 45),所以编码为1,
依次类推可得永丰立交纬度编码为101010111001001000100101101010。

1.2、经度也用同样的算法,对(-180, 180)依次细分,(-180,0)、(0,180) 得出编码110010011111101001100000000000

1.3、合并经纬度编码,从高到低,先取一位经度,再取一位纬度;得出结果 111001001100011111101011100011000010110000010001010001000100

1.4、用0-9、b-z(去掉a, i, l, o)这32个字母进行base32编码,得到(30.63578,104.031601)的编码为wm3yr31d2524。

1

2

3

4

5

6

11100 10011 00011 11110 10111 00011 00001 01100 00010 00101 00010 00100 => wm3yr31d2524

十进制  0   1   2   3   4   5   6   7   8   9   10  11  12  13  14  15

base32   0   1   2   3   4   5   6   7   8   9   b   c   d   e   f   g

十进制  16  17  18  19  20  21  22  23  24  25  26  27  28  29  30  31

base32   h   j   k   m   n   p   q   r   s   t   u v   w   x   y   z

2、策略

1、在纬度和经度入库时,数据库新加一字段geohash,记录此点的geohash值

2、查找附近,利用 在SQL中 LIKE ‘wm3yr3%’;且此结果可缓存;在小区域内,不会因为改变经纬度,而重新数据库查询

3、查找出的有限结果,如需要求距离或者排序,可利用距离公式和二维数据排序;此时也是少量数据,会很快的。

3、PHP基类

geohash.class.php

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

<?php

/**

* Encode and decode geohashes

*

*/

class Geohash

{

private $coding= "0123456789bcdefghjkmnpqrstuvwxyz" ;

private $codingMap=array();

public function Geohash()

{

for ($i=0; $i<32; $i++)

{

$this->codingMap[substr($this->coding,$i,1)]=str_pad(decbin($i), 5, "0" , STR_PAD_LEFT);

}

}

public function decode($ hash )

{

$binary= "" ;

$hl=strlen($ hash );

for ($i=0; $i<$hl; $i++)

{

$binary.=$this->codingMap[substr($ hash ,$i,1)];

}

$bl=strlen($binary);

$blat= "" ;

$blong= "" ;

for ($i=0; $i<$bl; $i++)

{

if ($i%2)

$blat=$blat.substr($binary,$i,1);

else

$blong=$blong.substr($binary,$i,1);

}

$lat=$this->binDecode($blat,-90,90);

$long=$this->binDecode($blong,-180,180);

$latErr=$this->calcError(strlen($blat),-90,90);

$longErr=$this->calcError(strlen($blong),-180,180);

$latPlaces=max(1, -round(log10($latErr))) - 1;

$longPlaces=max(1, -round(log10($longErr))) - 1;

$lat=round($lat, $latPlaces);

$long=round($long, $longPlaces);

return array($lat,$long);

}

public function encode($lat,$long)

{

$plat=$this->precision($lat);

$latbits=1;

$err=45;

while ($err>$plat)

{

$latbits++;

$err/=2;

}

$plong=$this->precision($long);

$longbits=1;

$err=90;

while ($err>$plong)

{

$longbits++;

$err/=2;

}

$bits=max($latbits,$longbits);

$longbits=$bits;

$latbits=$bits;

$addlong=1;

while (($longbits+$latbits)%5 != 0)

{

$longbits+=$addlong;

$latbits+=!$addlong;

$addlong=!$addlong;

}

$blat=$this->binEncode($lat,-90,90, $latbits);

$blong=$this->binEncode($long,-180,180,$longbits);

$binary= "" ;

$uselong=1;

while (strlen($blat)+strlen($blong))

{

if ($uselong)

{

$binary=$binary.substr($blong,0,1);

$blong=substr($blong,1);

}

else

{

$binary=$binary.substr($blat,0,1);

$blat=substr($blat,1);

}

$uselong=!$uselong;

}

$ hash = "" ;

for ($i=0; $i<strlen($binary); $i+=5)

{

$n=bindec(substr($binary,$i,5));

$ hash =$ hash .$this->coding[$n];

}

return $ hash ;

}

private function calcError($bits,$min,$max)

{

$err=($max-$min) /2 ;

while ($bits--)

$err/=2;

return $err;

}

private function precision($number)

{

$precision=0;

$pt=strpos($number, '.' );

if ($pt!== false )

{

$precision=-(strlen($number)-$pt-1);

}

return pow(10,$precision) /2 ;

}

private function binEncode($number, $min, $max, $bitcount)

{

if ($bitcount==0)

return "" ;

$mid=($min+$max) /2 ;

if ($number>$mid)

return "1" .$this->binEncode($number, $mid, $max,$bitcount-1);

else

return "0" .$this->binEncode($number, $min, $mid,$bitcount-1);

}

private function binDecode($binary, $min, $max)

{

$mid=($min+$max) /2 ;

if (strlen($binary)==0)

return $mid;

$bit=substr($binary,0,1);

$binary=substr($binary,1);

if ($bit==1)

return $this->binDecode($binary, $mid, $max);

else

return $this->binDecode($binary, $min, $mid);

}

}

?>

三、测试

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

<?php

require_once( 'Mysql.class.php' );

require_once( 'geohash.class.php' );

//mysql

$conf = array(

'host' => '127.0.0.1' ,

'port' => 3306,

'user' => 'root' ,

'password' => '123456' ,

'database' => 'mocube' ,

'charset' => 'utf8' ,

'persistent' => false

);

$mysql = new Db_Mysql($conf);

$geohash=new Geohash;

// 经纬度转换成Geohash

/*

$sql = 'select shop_id,latitude,longitude from mb_shop_ext' ;

$data = $mysql->queryAll($sql);

foreach($data as $val)

{

$geohash_val = $geohash->encode($val[ 'latitude' ],$val[ 'longitude' ]);

$sql = 'update mb_shop_ext set geohash= "' .$geohash_val. '" where shop_id = ' .$val[ 'shop_id' ];

echo $sql;

$re = $mysql->query($sql);

var_dump($re);

}

*/

// 获取附近的信息

$n_latitude = $_GET[ 'la' ];

$n_longitude = $_GET[ 'lo' ];

// 开始

$b_time = microtime( true );

// 方案A,直接利用数据库存储函数,遍历排序

/*

$sql = 'SELECT *,latitude,longitude,GETDISTANCE(latitude,longitude,' .$n_latitude. ',' .$n_longitude. ') AS distance FROM  mb_shop_ext where 1 HAVING distance<1000 ORDER BY distance ASC' ;

$data = $mysql->queryAll($sql);

// 结束

$e_time = microtime( true );

echo $e_time - $b_time;

var_dump($data);

exit ;

*/

// 方案B geohash求出附近,然后排序

// 当前 geohash值

$n_geohash = $geohash->encode($n_latitude,$n_longitude);

// 附近

$n = $_GET[ 'n' ];

$like_geohash = substr($n_geohash, 0, $n);

$sql = 'select * from mb_shop_ext where geohash like "' .$like_geohash. '%"' ;

echo $sql;

$data = $mysql->queryAll($sql);

// 算出实际距离

foreach($data as $key=>$val)

{

$distance = getDistance($n_latitude,$n_longitude,$val[ 'latitude' ],$val[ 'longitude' ]);

$data[$key][ 'distance' ] = $distance;

// 排序列

$sortdistance[$key] = $distance;

}

// 距离排序

array_multisort($sortdistance,SORT_ASC,$data);

// 结束

$e_time = microtime( true );

echo $e_time - $b_time;

var_dump($data);

// 根据经纬度计算距离 其中A($lat1,$lng1)、B($lat2,$lng2)

function getDistance($lat1,$lng1,$lat2,$lng2)

{

// 地球半径

$R = 6378137;

// 将角度转为狐度

$radLat1 = deg2rad($lat1);

$radLat2 = deg2rad($lat2);

$radLng1 = deg2rad($lng1);

$radLng2 = deg2rad($lng2);

// 结果

$s = acos(cos($radLat1)*cos($radLat2)*cos($radLng1-$radLng2)+sin($radLat1)*sin($radLat2))*$R;

// 精度

$s = round($s* 10000) /10000 ;

return  round($s);

}

?>

四、总结

方案B的亮点在于:
1、搜索结果可缓存,重复使用,不会因为用户有小范围的移动,直接穿透数据库查询。
2、先缩小结果范围,再运算、排序,可提升性能。

254条记录,性能对比,

在实际应用场景中,方案B数据库搜索可内存缓存;且如数据量更大,方案B结果会更优。

方案A:
0.016560077667236
0.032402992248535
0.040318012237549

方案B
0.0079810619354248
0.0079669952392578
0.0064868927001953

五、其他

两种方案,根据应用场景以及负载情况合理选择,当然推荐方案B;
不管哪种方案,都记得,给列加上索引,利于数据库检索。

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
3个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Stella981 Stella981
3年前
KVM调整cpu和内存
一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
9个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这