1.概述

最近有被留言关于ClickHouse的使用问题,今天笔者将为大家分享一下ClickHouse的安装细节和使用方法。

2.内容

首先安装环境如下所示:

  • Linux:CentOS7
  • ClickHouse:21.8.10.19

2.1 ClickHouse是什么?

ClickHouse是一个真正的列式数据库管理系统,在ClickHouse中,数据始终是按照列来进行存储的,包括矢量(向量或者列块)执行的过程。只要有可能,操作都是基于矢量进行分派的,而不是单个的值,这被称为矢量化查询执行,它有利于降低实际的数据处理开销。

这个想法并不新鲜,矢量编程被大量用于科学数据处理中。即使在关系型数据库中,这个想法也不是什么新的东西。通常有两种不同的加速查询处理的方法:矢量化查询执行和运行时代码生成。在后者中,动态的为每一类查询生成代码,消除了间接分派和动态分派。这两种方法中,并没有哪一种严格地比另一种好。运行时代码生成可以更好的将多个操作融合在一起,从而充分利用CPU执行单元和流水线。矢量化查询执行不是特别使用,因为它涉及必须写到缓存并读回的临时向量。如果L2缓存容纳不下临时数据,那么这将成为一个问题,但是矢量化查询执行更加容易利用CPU。

2.2 列

要表示内存中的列(实际上是列块),需使用 IColumn 接口。该接口提供了用于实现各种关系操作符的辅助方法。几乎所有的操作都是不可变的:这些操作不会更改原始列,但是会创建一个新的修改后的列。比如,IColumn::filter 方法接受过滤字节掩码,用于 WHERE 和 HAVING 关系操作符中。另外的例子:IColumn::permute 方法支持 ORDER BY 实现,IColumn::cut 方法支持 LIMIT 实现等等。
不同的 IColumn 实现(ColumnUInt8、ColumnString 等)负责不同的列内存布局。内存布局通常是一个连续的数组。对于数据类型为整型的列,只是一个连续的数组,比如 std::vector。对于 String 列和 Array 列,则由两个向量组成:其中一个向量连续存储所有的 String 或数组元素,另一个存储每一个 String 或 Array 的起始元素在第一个向量中的偏移。而 ColumnConst 则仅在内存中存储一个值,但是看起来像一个列。

2.3 字段

尽管如此,有时候也可能需要处理单个值。表示单个值,可以使用 Field。Field 是 UInt64、Int64、Float64、String 和 Array 组成的联合。IColumn 拥有 operator[] 方法来获取第 n 个值成为一个 Field,同时也拥有 insert 方法将一个 Field 追加到一个列的末尾。这些方法并不高效,因为它们需要处理表示单一值的临时 Field 对象,但是有更高效的方法比如 insertFrom 和 insertRangeFrom 等。
Field 中并没有足够的关于一个表(table)的特定数据类型的信息。比如,UInt8、UInt16、UInt32 和 UInt64 在 Field 中均表示为 UInt64。

2.4 数据类型

IDataType 负责序列化和反序列化:读写二进制或文本形式的列或单个值构成的块。IDataType 直接与表的数据类型相对应。比如,有 DataTypeUInt32、DataTypeDateTime、DataTypeString 等数据类型。
IDataType 与 IColumn 之间的关联并不大。不同的数据类型在内存中能够用相同的 IColumn 实现来表示。比如,DataTypeUInt32 和 DataTypeDateTime 都是用 ColumnUInt32 或 ColumnConstUInt32 来表示的。另外,相同的数据类型也可以用不同的 IColumn 实现来表示。比如,DataTypeUInt8 既可以使用 ColumnUInt8 来表示,也可以使用过 ColumnConstUInt8 来表示。
IDataType 仅存储元数据。比如,DataTypeUInt8 不存储任何东西(除了 vptr);DataTypeFixedString 仅存储 N(固定长度字符串的串长度)。
IDataType 具有针对各种数据格式的辅助函数。比如如下一些辅助函数:序列化一个值并加上可能的引号;序列化一个值用于 JSON 格式;序列化一个值作为 XML 格式的一部分。辅助函数与数据格式并没有直接的对应。比如,两种不同的数据格式 Pretty 和 TabSeparated 均可以使用 IDataType 接口提供的 serializeTextEscaped 这一辅助函数。

2.5 块

Block 是表示内存中表的子集(chunk)的容器,是由三元组:(IColumn, IDataType, 列名) 构成的集合。在查询执行期间,数据是按 Block 进行处理的。如果我们有一个 Block,那么就有了数据(在 IColumn 对象中),有了数据的类型信息告诉我们如何处理该列,同时也有了列名(来自表的原始列名,或人为指定的用于临时计算结果的名字)。
当我们遍历一个块中的列进行某些函数计算时,会把结果列加入到块中,但不会更改函数参数中的列,因为操作是不可变的。之后,不需要的列可以从块中删除,但不是修改。这对于消除公共子表达式非常方便。
Block 用于处理数据块。注意,对于相同类型的计算,列名和类型对不同的块保持相同,仅列数据不同。最好把块数据(block data)和块头(block header)分离开来,因为小块大小会因复制共享指针和列名而带来很高的临时字符串开销。

3.安装ClickHouse

在Github上搜索ClickHouse,并下载二进制安装包,下载内容如下:

下载地址如下:

https://github.com/ClickHouse/ClickHouse/releases

安装步骤如下:

## 第1步
# 解压common包
tar -zxvf clickhouse-common-static-21.8.10.19.tgz
tar -zxvf clickhouse-common-static-dbg-21.8.10.19.tgz # 执行脚本安装
sudo doinst.sh ## 第2步
# 解压server包
tar -zxvf clickhouse-server-21.8.10.19.tgz # 修改config.xml存储路径和监听端口
<!-- 实际数据存储路径,建议用一个磁盘空间较大的目录 -->
<path>/appcom/clickhouse/data/</path>
<tmp_path>/appcom/clickhouse/data/tmp/</tmp_path> <!-- 开启远程访问 -->
<listen_host>::</listen_host> # 执行脚本安装
sudo doinst.sh ## 第3步
# 解压client包
tar -zxvf clickhouse-client-21.8.10.19.tgz # 执行脚本安装
sudo doinst.sh ## 第4步
# 启动ClickHouse
/etc/init.d/clickhouse-server start ## 第5步
# 启动Client
clickhouse-client -m -h 127.0.0.1 --user default --port 9000 --password ckxxx

4.实战

4.1 准备实战数据

在Linux控制台中执行如下命令,获取表数据。命令如下所示:

# 获取表数据
curl https://datasets.clickhouse.com/hits/tsv/hits_v1.tsv.xz | unxz --threads=`nproc` > hits_v1.tsv curl https://datasets.clickhouse.com/visits/tsv/visits_v1.tsv.xz | unxz --threads=`nproc` > visits_v1.tsv

4.2 创建数据库和表

如果是使用ClickHouse Client执行建表语句,启动Client时,需要指定 -m 的参数,具体命令如下:

-- 创建数据库
CREATE DATABASE IF NOT EXISTS tutorial; -- 创建表(hits_v1)所有用户在服务所涵盖的所有网站上完成的每个操作
CREATE TABLE tutorial.hits_v1
(
`WatchID` UInt64,
`JavaEnable` UInt8,
`Title` String,
`GoodEvent` Int16,
`EventTime` DateTime,
`EventDate` Date,
`CounterID` UInt32,
`ClientIP` UInt32,
`ClientIP6` FixedString(16),
`RegionID` UInt32,
`UserID` UInt64,
`CounterClass` Int8,
`OS` UInt8,
`UserAgent` UInt8,
`URL` String,
`Referer` String,
`URLDomain` String,
`RefererDomain` String,
`Refresh` UInt8,
`IsRobot` UInt8,
`RefererCategories` Array(UInt16),
`URLCategories` Array(UInt16),
`URLRegions` Array(UInt32),
`RefererRegions` Array(UInt32),
`ResolutionWidth` UInt16,
`ResolutionHeight` UInt16,
`ResolutionDepth` UInt8,
`FlashMajor` UInt8,
`FlashMinor` UInt8,
`FlashMinor2` String,
`NetMajor` UInt8,
`NetMinor` UInt8,
`UserAgentMajor` UInt16,
`UserAgentMinor` FixedString(2),
`CookieEnable` UInt8,
`JavascriptEnable` UInt8,
`IsMobile` UInt8,
`MobilePhone` UInt8,
`MobilePhoneModel` String,
`Params` String,
`IPNetworkID` UInt32,
`TraficSourceID` Int8,
`SearchEngineID` UInt16,
`SearchPhrase` String,
`AdvEngineID` UInt8,
`IsArtifical` UInt8,
`WindowClientWidth` UInt16,
`WindowClientHeight` UInt16,
`ClientTimeZone` Int16,
`ClientEventTime` DateTime,
`SilverlightVersion1` UInt8,
`SilverlightVersion2` UInt8,
`SilverlightVersion3` UInt32,
`SilverlightVersion4` UInt16,
`PageCharset` String,
`CodeVersion` UInt32,
`IsLink` UInt8,
`IsDownload` UInt8,
`IsNotBounce` UInt8,
`FUniqID` UInt64,
`HID` UInt32,
`IsOldCounter` UInt8,
`IsEvent` UInt8,
`IsParameter` UInt8,
`DontCountHits` UInt8,
`WithHash` UInt8,
`HitColor` FixedString(1),
`UTCEventTime` DateTime,
`Age` UInt8,
`Sex` UInt8,
`Income` UInt8,
`Interests` UInt16,
`Robotness` UInt8,
`GeneralInterests` Array(UInt16),
`RemoteIP` UInt32,
`RemoteIP6` FixedString(16),
`WindowName` Int32,
`OpenerName` Int32,
`HistoryLength` Int16,
`BrowserLanguage` FixedString(2),
`BrowserCountry` FixedString(2),
`SocialNetwork` String,
`SocialAction` String,
`HTTPError` UInt16,
`SendTiming` Int32,
`DNSTiming` Int32,
`ConnectTiming` Int32,
`ResponseStartTiming` Int32,
`ResponseEndTiming` Int32,
`FetchTiming` Int32,
`RedirectTiming` Int32,
`DOMInteractiveTiming` Int32,
`DOMContentLoadedTiming` Int32,
`DOMCompleteTiming` Int32,
`LoadEventStartTiming` Int32,
`LoadEventEndTiming` Int32,
`NSToDOMContentLoadedTiming` Int32,
`FirstPaintTiming` Int32,
`RedirectCount` Int8,
`SocialSourceNetworkID` UInt8,
`SocialSourcePage` String,
`ParamPrice` Int64,
`ParamOrderID` String,
`ParamCurrency` FixedString(3),
`ParamCurrencyID` UInt16,
`GoalsReached` Array(UInt32),
`OpenstatServiceName` String,
`OpenstatCampaignID` String,
`OpenstatAdID` String,
`OpenstatSourceID` String,
`UTMSource` String,
`UTMMedium` String,
`UTMCampaign` String,
`UTMContent` String,
`UTMTerm` String,
`FromTag` String,
`HasGCLID` UInt8,
`RefererHash` UInt64,
`URLHash` UInt64,
`CLID` UInt32,
`YCLID` UInt64,
`ShareService` String,
`ShareURL` String,
`ShareTitle` String,
`ParsedParams` Nested(
Key1 String,
Key2 String,
Key3 String,
Key4 String,
Key5 String,
ValueDouble Float64),
`IslandID` FixedString(16),
`RequestNum` UInt32,
`RequestTry` UInt8
)
ENGINE = MergeTree()
PARTITION BY toYYYYMM(EventDate)
ORDER BY (CounterID, EventDate, intHash32(UserID))
SAMPLE BY intHash32(UserID); -- 创建表(visits_v1)预先构建的会话,而不是单个操作
CREATE TABLE tutorial.visits_v1
(
`CounterID` UInt32,
`StartDate` Date,
`Sign` Int8,
`IsNew` UInt8,
`VisitID` UInt64,
`UserID` UInt64,
`StartTime` DateTime,
`Duration` UInt32,
`UTCStartTime` DateTime,
`PageViews` Int32,
`Hits` Int32,
`IsBounce` UInt8,
`Referer` String,
`StartURL` String,
`RefererDomain` String,
`StartURLDomain` String,
`EndURL` String,
`LinkURL` String,
`IsDownload` UInt8,
`TraficSourceID` Int8,
`SearchEngineID` UInt16,
`SearchPhrase` String,
`AdvEngineID` UInt8,
`PlaceID` Int32,
`RefererCategories` Array(UInt16),
`URLCategories` Array(UInt16),
`URLRegions` Array(UInt32),
`RefererRegions` Array(UInt32),
`IsYandex` UInt8,
`GoalReachesDepth` Int32,
`GoalReachesURL` Int32,
`GoalReachesAny` Int32,
`SocialSourceNetworkID` UInt8,
`SocialSourcePage` String,
`MobilePhoneModel` String,
`ClientEventTime` DateTime,
`RegionID` UInt32,
`ClientIP` UInt32,
`ClientIP6` FixedString(16),
`RemoteIP` UInt32,
`RemoteIP6` FixedString(16),
`IPNetworkID` UInt32,
`SilverlightVersion3` UInt32,
`CodeVersion` UInt32,
`ResolutionWidth` UInt16,
`ResolutionHeight` UInt16,
`UserAgentMajor` UInt16,
`UserAgentMinor` UInt16,
`WindowClientWidth` UInt16,
`WindowClientHeight` UInt16,
`SilverlightVersion2` UInt8,
`SilverlightVersion4` UInt16,
`FlashVersion3` UInt16,
`FlashVersion4` UInt16,
`ClientTimeZone` Int16,
`OS` UInt8,
`UserAgent` UInt8,
`ResolutionDepth` UInt8,
`FlashMajor` UInt8,
`FlashMinor` UInt8,
`NetMajor` UInt8,
`NetMinor` UInt8,
`MobilePhone` UInt8,
`SilverlightVersion1` UInt8,
`Age` UInt8,
`Sex` UInt8,
`Income` UInt8,
`JavaEnable` UInt8,
`CookieEnable` UInt8,
`JavascriptEnable` UInt8,
`IsMobile` UInt8,
`BrowserLanguage` UInt16,
`BrowserCountry` UInt16,
`Interests` UInt16,
`Robotness` UInt8,
`GeneralInterests` Array(UInt16),
`Params` Array(String),
`Goals` Nested(
ID UInt32,
Serial UInt32,
EventTime DateTime,
Price Int64,
OrderID String,
CurrencyID UInt32),
`WatchIDs` Array(UInt64),
`ParamSumPrice` Int64,
`ParamCurrency` FixedString(3),
`ParamCurrencyID` UInt16,
`ClickLogID` UInt64,
`ClickEventID` Int32,
`ClickGoodEvent` Int32,
`ClickEventTime` DateTime,
`ClickPriorityID` Int32,
`ClickPhraseID` Int32,
`ClickPageID` Int32,
`ClickPlaceID` Int32,
`ClickTypeID` Int32,
`ClickResourceID` Int32,
`ClickCost` UInt32,
`ClickClientIP` UInt32,
`ClickDomainID` UInt32,
`ClickURL` String,
`ClickAttempt` UInt8,
`ClickOrderID` UInt32,
`ClickBannerID` UInt32,
`ClickMarketCategoryID` UInt32,
`ClickMarketPP` UInt32,
`ClickMarketCategoryName` String,
`ClickMarketPPName` String,
`ClickAWAPSCampaignName` String,
`ClickPageName` String,
`ClickTargetType` UInt16,
`ClickTargetPhraseID` UInt64,
`ClickContextType` UInt8,
`ClickSelectType` Int8,
`ClickOptions` String,
`ClickGroupBannerID` Int32,
`OpenstatServiceName` String,
`OpenstatCampaignID` String,
`OpenstatAdID` String,
`OpenstatSourceID` String,
`UTMSource` String,
`UTMMedium` String,
`UTMCampaign` String,
`UTMContent` String,
`UTMTerm` String,
`FromTag` String,
`HasGCLID` UInt8,
`FirstVisit` DateTime,
`PredLastVisit` Date,
`LastVisit` Date,
`TotalVisits` UInt32,
`TraficSource` Nested(
ID Int8,
SearchEngineID UInt16,
AdvEngineID UInt8,
PlaceID UInt16,
SocialSourceNetworkID UInt8,
Domain String,
SearchPhrase String,
SocialSourcePage String),
`Attendance` FixedString(16),
`CLID` UInt32,
`YCLID` UInt64,
`NormalizedRefererHash` UInt64,
`SearchPhraseHash` UInt64,
`RefererDomainHash` UInt64,
`NormalizedStartURLHash` UInt64,
`StartURLDomainHash` UInt64,
`NormalizedEndURLHash` UInt64,
`TopLevelDomain` UInt64,
`URLScheme` UInt64,
`OpenstatServiceNameHash` UInt64,
`OpenstatCampaignIDHash` UInt64,
`OpenstatAdIDHash` UInt64,
`OpenstatSourceIDHash` UInt64,
`UTMSourceHash` UInt64,
`UTMMediumHash` UInt64,
`UTMCampaignHash` UInt64,
`UTMContentHash` UInt64,
`UTMTermHash` UInt64,
`FromHash` UInt64,
`WebVisorEnabled` UInt8,
`WebVisorActivity` UInt32,
`ParsedParams` Nested(
Key1 String,
Key2 String,
Key3 String,
Key4 String,
Key5 String,
ValueDouble Float64),
`Market` Nested(
Type UInt8,
GoalID UInt32,
OrderID String,
OrderPrice Int64,
PP UInt32,
DirectPlaceID UInt32,
DirectOrderID UInt32,
DirectBannerID UInt32,
GoodID String,
GoodName String,
GoodQuantity Int32,
GoodPrice Int64),
`IslandID` FixedString(16)
)
ENGINE = CollapsingMergeTree(Sign)
PARTITION BY toYYYYMM(StartDate)
ORDER BY (CounterID, StartDate, intHash32(UserID), VisitID)
SAMPLE BY intHash32(UserID);

4.3 加载数据

数据导入到ClickHouse是通过INSERT INTO方式完成的,查询类似许多SQL数据库。然而,数据通常是在一个提供支持序列化格式而不是VALUES子句(也支持)。执行命令如下所示:

# 导入hits_v1表数据
clickhouse-client --password ckxxx --query "INSERT INTO tutorial.hits_v1 FORMAT TSV" --max_insert_block_size=100000 < hits_v1.tsv # 导入visits_v1表数据
clickhouse-client --password ckxxx --query "INSERT INTO tutorial.visits_v1 FORMAT TSV" --max_insert_block_size=100000 < visits_v1.tsv

4.4 查询

这里查询,我们使用Hue来作为可视化界面,这里推荐大家使用JDBC的方式来连接ClickHouse,由于Hue的Python库sqlalchemy-clickhouse对ClickHouse的兼容很差,如果使用sqlalchemy的方式来连接ClickHouse,会出现很多不兼容的情况,同时,在使用JDBC的方式时,也推荐大家使用clickhouse4j-1.4.4.jar的驱动包,而不是clickhouse-jdbc驱动包,即使用cc.blynk.clickhouse.ClickHouseDriver来替代ru.yandex.clickhouse.ClickHouseDriver。Hue系统文件hue.ini的配置内容如下所示:

 [[[clickhouse]]]
name=ClickHouse
interface=jdbc
# ## Specific options for connecting to the ClickHouse server.
# ## The JDBC driver clickhouse-jdbc.jar and its related jars need to be in the CLASSPATH environment variable.
options='{"url": "jdbc:clickhouse://localhost:8123", "driver": "cc.blynk.clickhouse.ClickHouseDriver", "user": "default", "password": "ckxxx"}'

同时,在~/.bash_profile中配置clickhouse4j-1.4.4.jar的环境变量,内容如下:

export CLASSPATH=/appcom/clickhouse/app/clickhouse4j-1.4.4.jar

执行source ~/.bash_profile使环境变量立即生效。

4.4.1 AVG查询

SELECT
StartURL AS URL,
AVG(Duration) AS AvgDuration
FROM tutorial.visits_v1
WHERE StartDate BETWEEN '2014-03-23' AND '2014-03-30'
GROUP BY URL
ORDER BY AvgDuration DESC
LIMIT 10

预览截图如下:

4.4.2 SUM查询

SELECT
sum(Sign) AS visits,
sumIf(Sign, has(Goals.ID, 1105530)) AS goal_visits,
(100. * goal_visits) / visits AS goal_percent
FROM tutorial.visits_v1
WHERE (CounterID = 912887) AND (toYYYYMM(StartDate) = 201403) AND (domain(StartURL) = 'yandex.ru')

预览截图如下:

5.总结

ClickHouse属于灵活的MPP架构,支持在线扩展,简单方便,可组件高可用分布式集群。多服务器分布式处理数据,拥有完整的DBMS系统。底层数据列式存储,支持压缩,优化数据存储,优化索引数据,优化底层存储。同时,支持数据统计分析各种场景,支持类SQL查询,异地复制部署等。

6.结束语

这篇博客就和大家分享到这里,如果大家在研究学习的过程当中有什么问题,可以加群进行讨论或发送邮件给我,我会尽我所能为您解答,与君共勉!

另外,博主出书了《Kafka并不难学》和《Hadoop大数据挖掘从入门到进阶实战》,喜欢的朋友或同学, 可以在公告栏那里点击购买链接购买博主的书进行学习,在此感谢大家的支持。关注下面公众号,根据提示,可免费获取书籍的教学视频。

ClickHouse实战的更多相关文章

  1. clickhouse入门到实战及面试

    第一章. clickhouse入门 一.ClickHouse介绍 ClickHouse(开源)是一个面向列的数据库管理系统(DBMS),用于在线分析处理查询(OLAP). 关键词:开源.面向列.联机分 ...

  2. Zabbix实战-简易教程--DB类--ClickHouse

    一.ClickHouse介绍 Clickhouse是一个用于联机分析处理(OLAP)的列式数据库管理系统(columnar DBMS). 传统数据库在数据大小比较小,索引大小适合内存,数据缓存命中率足 ...

  3. MySQL到ClickHouse实时同步-CloudCanal实战

    简述 CloudCanal 近期实现了 MySQL(RDS) 到 ClickHouse 实时同步的能力,功能包含全量数据迁移.增量数据迁移.结构迁移能力,以及附带的监控.告警.HA等能力(平台自带). ...

  4. Apache Beam实战指南 | 大数据管道(pipeline)设计及实践

    Apache Beam实战指南 | 大数据管道(pipeline)设计及实践  mp.weixin.qq.com 策划 & 审校 | Natalie作者 | 张海涛编辑 | LindaAI 前 ...

  5. Greenplum实战之查询优化

    本文主要分为三部分: GP优化需要准备的一些关于优化之外的知识,包括清空缓存.性能监控.执行计划分析. 具体优化措施,从以下四个方面考虑: 表.字段 sql GP配置.服务器配置 硬件及节点资源 GP ...

  6. Apache Pulsar 在 BIGO 的性能调优实战(上)

    背景 在人工智能技术的支持下,BIGO 基于视频的产品和服务受到广泛欢迎,在 150 多个国家/地区拥有用户,其中包括 Bigo Live(直播)和 Likee(短视频).Bigo Live 在 15 ...

  7. ClickHouse学习系列之六【访问权限和账户管理】

    背景 在之前写的文章[用户权限管理]里已经介绍了应该如何设置用户密码以及权限控制.但是只是针对修改配置文件的方式来进行用户权限管理,其实ClickHouse也支持基于RBAC(Role-Based A ...

  8. Sentry 监控 - Snuba 数据中台架构简介(Kafka+Clickhouse)

    系列 1 分钟快速使用 Docker 上手最新版 Sentry-CLI - 创建版本 快速使用 Docker 上手 Sentry-CLI - 30 秒上手 Source Maps Sentry For ...

  9. Sentry 监控 - Snuba 数据中台本地开发环境配置实战

    系列 1 分钟快速使用 Docker 上手最新版 Sentry-CLI - 创建版本 快速使用 Docker 上手 Sentry-CLI - 30 秒上手 Source Maps Sentry For ...

随机推荐

  1. 模板引挚 jade ejs

    // asl sum翡翠 后台使用如下: const jade = require('jade') //pretty 美化的意思,指的是渲染的布局会美化   2020-2-15 var str = j ...

  2. 集合遍历数组三种常用方式(Collecton和Map)

    Collection集合遍历数组的三种方式: 迭代器 foreach(增强for循环) JDK1.8之后的新技术Lambda 迭代器: 方法:public Iterator inerator():获取 ...

  3. 测试开发【提测平台】分享10-Element UI抽屉和表单校验&增改接口合并实现应用管理

    微信搜索[大奇测试开],关注这个坚持分享测试开发干货的家伙. 开篇说个小讨论,一个群里聊天聊到关于更新篇章的长度,是小篇幅多次,还是每次按照一个小完整的功能,我个人的是按照后种来的,主要的思考就是希望 ...

  4. PHP中的一些杂项函数学习

    今天来学习的这些杂项函数在官方文档中都是放在一个杂项扩展中的,其实这些函数都并不是什么什么特别的扩展,也不需要安装什么东西就可以使用,它们就是一些简单的功能函数而已.当然,其中不少内容也是我们经常会使 ...

  5. 小程序跳转H5及其他页面

    一.小程序和公众号 答案是:可以相互关联. 在微信公众号里可以添加小程序. 图片有点小,我把文字打出来吧: 可关联已有的小程序或快速创建小程序.已关联的小程序可被使用在自定义菜单和模版消息等场景中. ...

  6. obs软件mac设置

    1 远程电脑软件teamview或者向日葵 远程mac电脑会时黑屏或连不上, 需要设置系统偏好->设置软件权限 2 设置obs 显示不出画面或声音,也需要在系统偏好设置obs的权限(首先打开OB ...

  7. TP5开启缓存

    https://www.kancloud.cn/manual/thinkphp5/215850 V5.0.6+版本开始,全局请求缓存支持设置排除规则,使用方法如下:config.php文件 'requ ...

  8. Java学习之随堂笔记系列——day01

    学习方法:听.问.敲.悟听:前提:上课要听懂,没有听懂可以及时的问.问:任何的问题都要及时的问.敲:重点内容.多写多练,只有写和练习才能发现新的问题,有问题就问.悟:举一反三.提升自己.今日内容:1. ...

  9. 关于selenium中的三种等待方式与EC模块的知识

    1. 强制等待 第一种也是最简单粗暴的一种办法就是强制等待sleep(xx),强制让闪电侠等xx时间,不管凹凸曼能不能跟上速度,还是已经提前到了,都必须等xx时间. 看代码: 1 2 3 4 5 6 ...

  10. P5074-Eat the Trees【插头dp】

    正题 题目链接:https://www.luogu.com.cn/problem/P5074 题目大意 给出一个\(n\times m\)的网格,有的必须铺线有的不能,铺成若干条闭合回路,求方案数. ...