hp-vertica数据库从入门到精通


第 1 页 共 182 页 Vertica 数据库从入门到精通 作 者: 李中原 创 作 日 期: 2014 年 07 月 24 日 最 近 修 改 日 期: 2015 年 01 月 08 日 文 档 控 制 号: 版 本: 1.3 第 2 页 共 182 页 文档控制 本文档以实践为主,主要参考《HP_Vertica_7.x.x_AdministratorsGuide》, 从 DBA 视角进行重新排版。本文仅供 vertica 数据库爱好者、开发人员、DBA 学习参考之用,未经本人授权不得用于商业目的。 变更记录 日期 作者 版本 变更描述 David 2014-07-24 李中原 1.0 创建文档 2014-08-29 李中原 1.1 更新、增加 2014-11-18 李中原 1.2 增加集群升级、MC 管理章节 2015-01-08 李中原 1.3 增加安全管理章节 发行 拷贝号 姓名 地址 1 2 3 4 第 3 页 共 182 页 目录 文档控制 ........................................................................................................................................................................................ 2 作者简介--李中原 ...................................................................................................................................................................... 7 1. VERTICA 数据库安装准备 .............................................................................................................................................. 7 1.1 安装模式选择 ................................................................................................................................................................... 7 1.2 硬件要求 ........................................................................................................................................................................... 7 1.3 操作系统版本 ................................................................................................................................................................... 8 1.3.1 Vertica7.X 版本 ................................................................................................................................................................. 8 1.4 配置 YUM 本地源 ............................................................................................................................................................. 8 1.5 操作系统时区 ................................................................................................................................................................... 9 1.6 REDHAT 6.4 操作系统的包、补丁和其它组件 ................................................................................................................. 9 1.6.1 安装必要的工具包 ........................................................................................................................................................... 9 1.6.2 文件系统配置 ................................................................................................................................................................... 9 1.6.3 网络参数与端口 ............................................................................................................................................................. 10 1.6.4 Vertica 安装脚本可以修复的系统参数 ........................................................................................................................ 10 1.6.5 Vertica 安装脚本无法修复的系统参数 ........................................................................................................................ 11 1.6.6 关闭 IPTABLES ................................................................................................................................................................. 11 1.7 增加开机启动的设置 ..................................................................................................................................................... 12 1.8 调整 NTP 协议 ................................................................................................................................................................ 12 1.9 关闭 SELINUX .................................................................................................................................................................... 13 1.10 新建用户 DBADMIN UID 是 601 .......................................................................................................................................... 14 1.11 创建软件安装目录 ......................................................................................................................................................... 14 1.12 DBADMIN 用户环境变量 ................................................................................................................................................... 15 1.13 DBADMIN 用户配置 SSH 信任关系 .................................................................................................................................... 15 1.14 配置 SSH LOGINGRACETIME 参数 ....................................................................................................................................... 15 2. VERTICA 集群的安装配置 ................................................................................................................................................ 16 2.1 VERTICA7.0.1 集群安装 .................................................................................................................................................... 16 2.2 集群增加节点 ................................................................................................................................................................. 19 2.3 集群删除节点 ................................................................................................................................................................. 21 2.4 集群升级 ......................................................................................................................................................................... 21 2.5 集群的 ACTIVE STANDBY 节点 ...................................................................................................................................... 24 2.5.1 创建 active standby 节点 ............................................................................................................................................... 24 2.5.2 替换 active standby 节点 ............................................................................................................................................... 24 2.5.3 反转 active standby 节点 ............................................................................................................................................... 25 第 4 页 共 182 页 3. VERTICA 的管理和维护.................................................................................................................................................... 25 3.1 增加磁盘 ......................................................................................................................................................................... 25 3.2 替换坏盘 ......................................................................................................................................................................... 28 3.3 回收磁盘空间 ................................................................................................................................................................. 29 3.3.1 重建表的过程 ........................................................................................................................................................ 29 3.4 存储位置 ......................................................................................................................................................................... 29 3.5 存储策略 ......................................................................................................................................................................... 31 4. VERTICA 数据库备份恢复 ................................................................................................................................................ 33 4.1 VERTICA 备份 ................................................................................................................................................................. 33 4.1.1 Vertica 备份环境准备 .................................................................................................................................................... 33 4.1.2 Vertica 备份配置文件 .................................................................................................................................................... 33 4.1.3 Vertica 全备份 ................................................................................................................................................................ 35 4.1.4 Vertica 增量备份 ............................................................................................................................................................ 36 4.1.5 Vertica 对象级备份 ........................................................................................................................................................ 42 4.1.6 Vertica HardLinkLocal 备份 ............................................................................................................................................ 43 4.1.7 Vertica 备份查询 ............................................................................................................................................................ 45 4.2 VERTICA 恢复 ................................................................................................................................................................. 46 4.2.1 Vertica 全量恢复 ............................................................................................................................................................ 47 4.2.2 Vertica 对象恢复 ............................................................................................................................................................ 48 4.2.3 Vertica 灾难恢复 ............................................................................................................................................................ 50 4.2.4 灾难恢复最佳实践 ......................................................................................................................................................... 51 4.3 VERTICA 集群拷贝 ......................................................................................................................................................... 51 5. PROJECTIONS ................................................................................................................................................................... 53 5.1 创建 PORJECTION ............................................................................................................................................................... 53 5.2 创建自定义 PORJECTION ................................................................................................................................................... 54 5.3 REPLICATED PROJECTIONS ...................................................................................................................................................... 57 5.4 分段的 PROJECTIONS .......................................................................................................................................................... 57 5.5 选择 ENCODING 和 COMPRESSION ........................................................................................................................................ 59 5.5.1 Encoding .......................................................................................................................................................................... 59 5.5.2 Compression .................................................................................................................................................................... 60 5.6 选择列的 SORT ORDER ...................................................................................................................................................... 60 5.7 程序中进行 PROJECTION 设计 ..................................................................................................................................... 61 5.7.1 何时进行设计 ................................................................................................................................................................. 61 5.7.2 设计相关函数 ................................................................................................................................................................. 62 5.7.3 设计案例 ......................................................................................................................................................................... 66 6. 负载均衡.......................................................................................................................................................................... 71 6.1 自带的负载均衡- NATIVE CONNECTION LOAD BALANCING .................................................................................................... 71 6.1.1 启用了自带负载均衡之后的连接过程: ..................................................................................................................... 72 6.1.2 负载均衡策略和实现 ..................................................................................................................................................... 72 6.2 IPVS 负载均衡- INTERNET PROTOCOL VIRTUAL SERVER ........................................................................................................... 73 7. 数据加载.......................................................................................................................................................................... 73 7.1 TUPLE MOVER 原理 ............................................................................................................................................................ 73 7.1.1 TM moveout .................................................................................................................................................................... 74 第 5 页 共 182 页 7.1.2 TM mergeout .................................................................................................................................................................. 75 7.1.3 TM 性能优化 .................................................................................................................................................................. 75 7.2 从文本文件 COPY 加载 .................................................................................................................................................... 77 8. VERTICA 监控 ................................................................................................................................................................... 78 8.1 系统日志 ......................................................................................................................................................................... 78 8.2 事件监控 ......................................................................................................................................................................... 79 8.3 数据收集器 ..................................................................................................................................................................... 82 8.4 工作负载分析器(WLA) ............................................................................................................................................ 83 8.5 诊断工具 - SCRUTINIZE ................................................................................................................................................. 85 8.6 诊断工具 - DIAGNOSTICS .............................................................................................................................................. 88 8.7 诊断工具 - COLLECT_DIAG_DUMP.SH .......................................................................................................................... 89 9. 权限和安全 ...................................................................................................................................................................... 89 9.1 普通操作权限 ................................................................................................................................................................. 90 9.1.1 SCHEMA 权限.................................................................................................................................................................. 90 9.1.2 创建表权限 ..................................................................................................................................................................... 91 9.1.3 创建视图权限 ................................................................................................................................................................. 96 9.1.4 创建 Projection 权限 ...................................................................................................................................................... 96 9.1.5 创建序列的权限 ............................................................................................................................................................. 97 9.1.6 IO 操作权限 .................................................................................................................................................................... 98 9.1.7 过程和函数权限 ............................................................................................................................................................. 98 9.2 角色权限 ......................................................................................................................................................................... 99 9.3 权限的管理 ................................................................................................................................................................... 101 9.3.1 用户权限管理 ............................................................................................................................................................... 101 9.3.2 存储位置权限管理 ....................................................................................................................................................... 105 9.4 安全管理 ....................................................................................................................................................................... 106 9.4.1 客户端身份验证 ........................................................................................................................................................... 106 9.4.2 管理客户端身份验证 ................................................................................................................................................... 108 9.4.3 客户端身份验证优先级 ............................................................................................................................................... 110 9.4.5 授权和撤销身份认证 ................................................................................................................................................... 111 9.4.6 修改身份认证方法 ....................................................................................................................................................... 111 9.4.7 获得身份认证记录 ....................................................................................................................................................... 112 9.4.8 密码认证方法 ............................................................................................................................................................... 112 9.4.9 LDAP 认证方法 ............................................................................................................................................................. 113 10. 性能优化 ................................................................................................................................................................... 113 10.1 资源管理器 - RESOURCE MANAGER ................................................................................................................................... 113 10.1.1 理解资源池的架构 ..................................................................................................................................................... 114 10.1.2 管理资源池 ................................................................................................................................................................. 115 10.1.3 资源负载管理最佳实践 ............................................................................................................................................. 117 10.2 统计信息收集 ............................................................................................................................................................... 124 10.2.1 如何收集统计信息 ..................................................................................................................................................... 125 10.2.2 统计信息收集最佳实践 ............................................................................................................................................. 127 10.2.3 导出 profile 数据 ........................................................................................................................................................ 128 10.3 理解执行计划 ............................................................................................................................................................... 128 第 6 页 共 182 页 10.3.1 如何获取执行计划 ..................................................................................................................................................... 129 10.3.2 理解执行计划 ............................................................................................................................................................. 130 10.4 使用 PROFILE ........................................................................................................................................................... 135 10.4.1 打开关闭 profile ......................................................................................................................................................... 135 10.4.2 Real-time profiling ....................................................................................................................................................... 137 10.4.3 使用 vsql 管理 profile ................................................................................................................................................. 138 10.5 优化查询语句 .......................................................................................................................................................... 140 10.5.1 优化编码方式 ............................................................................................................................................................. 141 10.5.2 优化带谓词的查询 Projection ................................................................................................................................... 142 10.5.3 优化 merge 操作的 Projection ................................................................................................................................... 144 10.5.4 优化 group by 子句 .................................................................................................................................................... 148 10.5.5 优化带 DISTINCT 的查询 ............................................................................................................................................ 154 10.5.6 优化关联查询 ............................................................................................................................................................. 155 10.5.7 优化 ORDER BY 查询 .................................................................................................................................................. 158 10.5.8 优化 SQL-99 分析函数 ............................................................................................................................................... 159 10.5.9 优化 LIMIT 查询.......................................................................................................................................................... 166 10.5.10 优化 INSERT-SELECT 语句 ......................................................................................................................................... 166 10.5.11 优化更新和删除操作 ............................................................................................................................................... 167 11. 常见问题处理 ............................................................................................................................................................ 169 11.1 数据库的后台进程被 KILL ............................................................................................................................................. 169 11.2 数据文件被删除 ........................................................................................................................................................... 170 11.2.1 删除 1 个节点数据文件 ............................................................................................................................................ 170 11.2.2 删除 2 个节点数据文件 ............................................................................................................................................ 172 11.3 CATALOG 文件被删除 ..................................................................................................................................................... 174 11.3.1 删除 1 个节点 catalog ............................................................................................................................................... 174 11.3.1 删除 2 个节点 catalog ............................................................................................................................................... 175 11.4 私有网络 DOWN 集群 CRASH .................................................................................................................................. 176 12. 管理控制台(MC) .................................................................................................................................................... 177 12.1 管理控制台架构 .............................................................................................................................................................. 177 12.2 管理控制台的安装和配置 .............................................................................................................................................. 178 12.3 管理控制台的维护 .......................................................................................................................................................... 179 12.3.1 管理控制台重启 ......................................................................................................................................................... 179 12.3.2 重设 MC 到初始状态 ................................................................................................................................................. 179 12.4 修改 MC AGENT 端口 ..................................................................................................................................................... 180 12.4.1 修改 config.py 中的 Agent Port.................................................................................................................................. 180 12.5 MC 的用户管理 ............................................................................................................................................................... 180 13. 名词解释 ................................................................................................................................................................... 181 13.1 PRO-JOIN PROJECTION ........................................................................................................................................................ 181 第 7 页 共 182 页 作者简介--李中原 毕业于哈尔滨工业大学,丰富的数据库运维、项目实施和故障 处理经验,有上超大规模 DataGuard 环境优化的经验,在容 灾演练和故障切换上有特别丰富的经验。曾在甲骨文工作,任 售后支持工程师,期间主要对客户故障应急支持、根因分析, 并对部分客户关键系统进行持续的性能优化,积累了丰富的经 验和形成一套优化方法论和实践,在 RAC、DATAGUARD 、 GOLDENGA TE 等领域技术见长。目前正在探索大数据和分 布式计算相关技术。 邮件:lizy52102@gmail.com QQ:zhongyuan.li@oracle.com 1. Vertica 数据库安装准备 1.1 安装模式选择 Vertica 主要有以下四种安装模式 序号 安装模式 配置要求总结 1 本机 localhost 模式 如果使用 localhost 或者 loopback 127.0.0.1 作为-- hosts,该模式不能扩展成集群,如果有机会扩展的情况 下不要使用 localhost 作为--hosts 2 物理集群模式 需要配置 3 亚马逊 AWS(Amazon Web Services) 模式 4 虚拟机模式 和物理机模式类似,不过网络配置有所不同 1.2 硬件要求  内存至少 RAM 1GB/CPU 第 8 页 共 182 页  SWAP 区: 当内存<=2GB 时,swap=1.5*RAM >=2GB 当 2GB< 内存<=8GB 时,swap=RAM 当内存> 8GB 时,swap=0.75*RAM(48GB) 1.3 操作系统版本 1.3.1 Vertica7.X 版本 对于 Vertica 7.X 版本,其操作详细要求如下: 序号 文档名称 配置要求总结 1 Red Hat Enterprise Linux 5 and 6 2 SUSE Linux Enterprise Server 11 3 Oracle Enterprise Linux 6 - Red Hat Compatible Kernel only - HP Vertica does not support the unbreakable kernel (kernels with a uel suffix) 4 Debian Linux 6 5 Cent OS 5 and 6 6 Ubuntu 12.04LTS 本文以下的所有安装配置都是以 redhat 6.4 为例,其它版本操作系统请参考安装说明配置。 1.4 配置 YUM 本地源 root 用户登录: cd /etc/yum.repos.d mv rhel-source.repo rhel-source.repo.bak vi rhel-source.repo [redhat6] name = Redhat Linux 6.4 DVD baseurl=file:///media/"RHEL_6.4 x86_64 Disc 1"/Server gpgcheck=0 enabled=1 说明,红色部分是光盘的 mount 点,有空格的加双引号"" 测试 yum 本地源 yum list 第 9 页 共 182 页 1.5 操作系统时区 #检查 /etc/sysconfig/clock grep ZONE /etc/sysconfig/clock ZONE="Asia/Shanghai" 1.6 Redhat 6.4 操作系统的包、补丁和其它组件 根据文档《HP_Vertica_7.0.x_Install_Guide》,在安装操作系统版本后,还需要与之相匹配的包和补丁。 1.6.1 安装必要的工具包 ## 要求安装以下软件包 yum -y install pstack mcelog sysstat ## 检查 yum list pstack mcelog sysstat 1.6.2 文件系统配置 Vertica 存储数据文件和 catalog 文件的目录要求使用 ext3 或 ext4 ## 检查存储数据文件和 catalog 文件的磁盘是否使用 lvm lvm lvscan ##检查 IO Scheduler 设置 echo deadline > /sys/block/sda/queue/scheduler ## 检查磁盘的预读取设置 /sbin/blockdev --setra 8192 /dev/sda ## 检查 hugepage 设置 echo never > /sys/kernel/mm/redhat_transparent_hugepage/enabled 第 10 页 共 182 页 1.6.3 网络参数与端口 Vertica 需要开通以下端口: 端口 协议 服务 说明 22 TCP sshd Required by Administration Tools and the Management Console Cluster Installation wizard. 5433 TCP HP Vertica HP Vertica client (vsql, ODBC, JDBC,etc) port. 5434 TCP HP Vertica Intra-clustercommunication. HP Vertica opens the HP Vertica client port +1(5434 by default)for intra-cluster communication, such as during a plan. If the port +1 fro mthe default client port is not available, then HP Vertica opens a random port for intra- cluster communication. 5433 UDP HP Vertica HP Vertica spread monitoring. 5444 TCP HP Vertica Management Console MC-to-node and node-to-node(agent) communications port. 5450 TCP HP Vertica Management Console Port used toconnect to MC from a web browser and allows communication from nodes to the MC application/webserver. 4803 TCP Spread Client connections. 4803 UDP Spread Daemon to Daemon connections. 4804 UDP Spread Daemon to Daemon connections. 6543 UDP Spread Monitor to Daemon connection. 1.6.4 Vertica 安装脚本可以修复的系统参数 序号 配置项 说明 1 Nice Limits The database administration user must be able to nice processes back to the default level of 0. 2 min_free_kbytes The vm.min_free_kbytes setting in/etc/sysctl.conf must be configured sufficiently high. The specific value depends on your hardware configuration. 3 User Open Files Limit The open file limit for the dbadmin user should be at least 1 file open perMB of RAM, 65536, or the amount of RAM inMB; whichever is greater. 4 System Open File Limits The maximum number of files open on the system must not be less than at least the amount of memory in MB, but not less 第 11 页 共 182 页 than 65536. 5 Pam Limits /etc/pam.d/su must contain the line : session required pam_limits.so This allows for the conveying of limits to commands run with the su command. 6 Address Space Limits Space Limits Thead dress space limits (as setting)defined in/etc/security/limits.conf must be unlimited for the database administrator. 7 fileSize Limits The file size limits (fsize setting) defined in/etc/security/limits.conf must be unlimited for the database administrator. 8 UserProcess Limits The nproc setting defined in/etc/security/limits.conf must be 1024 or the amount of memory in MB, whichever is greater. 9 Maximum Memory Maps The vm.max_map_count in/etc/sysctl.conf must be 65536 or the amount of memory in KB / 16, whichever is greater . 1.6.5 Vertica 安装脚本无法修复的系统参数 序号 配置项 说明 1 Disk Readahead This disk readahead must beat least 2048. The specific value depends on your hardware configuration. 2 NTP Services The NTP daemon must be enabled and running. 3 SELinux SElinux must be disabled or run in permissive mode. 4 CPU Frequency Scaling HP Vertica recommends that you disable CPU Frequency Scaling. Important: Your systems may use significantly more energy when CPU frequency scalingis disabled. 5 Transparent Hugepages Transparent Hugepages should be disabled or set to madvise. 6 I/O Scheduler The I/O Scheduler for disks used by HP Vertica must be set to deadline or noop. 1.6.6 关闭 IPTABLES service iptables save service iptables stop chkconfig iptables off service ip6tables save service ip6tables stop 第 12 页 共 182 页 chkconfig ip6tables off 1.7 增加开机启动的设置 ## /etc/rc.d/rc.local 确认一下内容是否已经添加: echo deadline > /sys/block/sda/queue/scheduler /sbin/blockdev --setra 8192 /dev/sda echo never > /sys/kernel/mm/redhat_transparent_hugepage/enabled 1.8 调整 NTP 协议 Vertica 集群要求在集群内的所有节点配置时间同步服务,可以采用 ntp #节点 1 配置成 server vi /etc/ntp.conf server 127.127.1.0 fudge 127.127.1.0 stratum 8 #节点 2、3 配置成 client vi /etc/ntp.conf server 10.75.7.110 /sbin/service ntpd restart /sbin/chkconfig ntpd on #节点 1 检查同步状态 watch ntpq -p #节点 2、3 检查是否同步 ntpdate -d 10.75.7.110 第 13 页 共 182 页 1.9 关闭 SELinux Vertica 不支持 SELinux,除非其运行在 permissive,如果安装进程监测到安装了 SELinux 但是无法 判断运行模式会报 S0080,如果能够判断模式,但不是运行在 permissive 模式的话会报 S0081。 检查是否启用 SELinux 的方法是:/usr/sbin/sestatus -v [dbadmin@dws1 ~]$ /usr/sbin/sestatus -v SELinux status: enabled SELinuxfs mount: /selinux Current mode: enforcing Mode from config file: enforcing Policy version: 24 Policy from config file: targeted Process contexts: Current context: unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 Init context: system_u:system_r:init_t:s0 File contexts: Controlling term: unconfined_u:object_r:user_devpts_t:s0 /etc/passwd system_u:object_r:etc_t:s0 /etc/shadow system_u:object_r:shadow_t:s0 /bin/bash system_u:object_r:shell_exec_t:s0 /bin/login system_u:object_r:login_exec_t:s0 /bin/sh system_u:object_r:bin_t:s0 -> system_u:object_r:shell_exec_t:s0 /sbin/agetty system_u:object_r:getty_exec_t:s0 /sbin/init system_u:object_r:init_exec_t:s0 /sbin/mingetty system_u:object_r:getty_exec_t:s0 /usr/sbin/sshd system_u:object_r:sshd_exec_t:s0 /lib/libc.so.6 system_u:object_r:lib_t:s0 -> system_u:object_r:lib_t:s0 /lib/ld-linux.so.2 system_u:object_r:lib_t:s0 -> system_u:object_r:ld_so_t:s0 临时关闭 SELinux 的方法:setenforce 0 ,设置 SELinux 成为 permissive 模式;setenforce 1 设 置 SELinux 成为 enforcing 模式。 [root@dws1 ~]# setenforce 0 [root@dws1 ~]# [root@dws1 ~]# getenforce Permissive [root@dws1 ~]# /usr/sbin/sestatus -v SELinux status: enabled SELinuxfs mount: /selinux Current mode: permissive 第 14 页 共 182 页 Mode from config file: enforcing Policy version: 24 Policy from config file: targeted Process contexts: Current context: unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 Init context: system_u:system_r:init_t:s0 /sbin/mingetty system_u:system_r:getty_t:s0 /usr/sbin/sshd system_u:system_r:sshd_t:s0-s0:c0.c1023 File contexts: Controlling term: unconfined_u:object_r:user_devpts_t:s0 /etc/passwd system_u:object_r:etc_t:s0 /etc/shadow system_u:object_r:shadow_t:s0 /bin/bash system_u:object_r:shell_exec_t:s0 /bin/login system_u:object_r:login_exec_t:s0 /bin/sh system_u:object_r:bin_t:s0 -> system_u:object_r:shell_exec_t:s0 /sbin/agetty system_u:object_r:getty_exec_t:s0 /sbin/init system_u:object_r:init_exec_t:s0 /sbin/mingetty system_u:object_r:getty_exec_t:s0 /usr/sbin/sshd system_u:object_r:sshd_exec_t:s0 /lib/libc.so.6 system_u:object_r:lib_t:s0 -> system_u:object_r:lib_t:s0 /lib/ld-linux.so.2 system_u:object_r:lib_t:s0 -> system_u:object_r:ld_so_t:s0 要彻底关闭,通过修改配置文件/etc/selinux/config,将 SELINUX=enforcing 改为 SELINUX=disabled,该修改需要重启生效。 1.10 新建用户 dbadmin uid 是 601 Vertica 安装脚本在未指定的情况下能够创建 dbadmin 用户,但是为了保证 dbadmin 在集群间的 uid、 gid 一致,还是使用手动的方式创建。 groupadd -g 601 verticadba useradd -u 601 -g 601 dbadmin 1.11 创建软件安装目录 mkdir -p /home/dbadmin/data mkdir -p /home/dbadmin/catalog 为了避免出现误删除等情况,生产系统改成单独的卷/data 和/catalog 目录 第 15 页 共 182 页 1.12 dbadmin 用户环境变量 【dbadmin】用户环境变量: #设置环境变量值 su - dbadmin vi .bash_profile export TZ= Asia/Shanghai #退出重新登录 dbadmin echo $TZ Asia/Shanghai 1.13 dbadmin 用户配置 ssh 信任关系 Vertica 安装脚本会自动配置 ssh 信任关系,一般不需要手动配置,如果特殊情况需要自行配置时操作脚本 如下: 【节点 1】 cd ~/.ssh ssh-keygen -q -t rsa -f ~/.ssh/vid_rsa -N '' cat vid_rsa.pub > vauthorized_keys2 cat vid_rsa.pub >> authorized_keys2 chmod 600 ~/.ssh/* scp -r /root/.ssh/vauthorized_keys2 V2:/root/.ssh/. scp -r /root/.ssh/vauthorized_keys2 V3:/root/.ssh/. 【节点 2】 cd /root/.ssh/; cat vauthorized_keys2 >> authorized_keys2; chmod 600 /root/.ssh/authorized_keys2" 【节点 3】 cd /root/.ssh/; cat vauthorized_keys2 >> authorized_keys2; chmod 600 /root/.ssh/authorized_keys2" ssh -i /root/.ssh/vid_rsa V2 "rm /root/.ssh/vauthorized_keys2" ssh -i /root/.ssh/vid_rsa V3 "rm /root/.ssh/vauthorized_keys2" rm ~/.ssh/vauthorized_keys2 测试是否成功: ssh V1 date ssh V2 date ssh V3 date 1.14 配置 SSH LoginGraceTime 参数 On Linux systems, OpenSSH 参数 LoginGraceTime 默认屏蔽掉了 [root 用户] 1.编辑文件 /etc/ssh/sshd_config 第 16 页 共 182 页 2. Locate the comment line #LoginGraceTime 2m. 3. Uncomment the line, and change the value to 0 (unlimited). For example: LoginGraceTime 0 4. Save /etc/ssh/sshd_config 5. Restart SSH. service restart sshd 2. Vertica 集群的安装配置 2.1 Vertica7.0.1 集群安装 Root 用户登录并执行以下命令: rpm -Uvh /home/vertica/vertica-7.0.1-0.x86_64.RHEL5.rpm /opt/vertica/sbin/install_vertica --hosts 10.75.7.110,10.75.7.111,10.75.7.112 --rpm /home/vertica/vertica-7.0.1-0.x86_64.RHEL5.rpm --dba-user dbadmin Vertica Analytic Database 7.0.1-0 Installation Tool >> Validating options... Mapping hostnames in --hosts (-s) to addresses... >> Starting installation tasks. >> Getting system information for cluster (this may take a while)... Enter password for root@10.75.7.111 (3 attempts left): Default shell on nodes: 10.75.7.111 /bin/bash 10.75.7.110 /bin/bash 10.75.7.112 /bin/bash >> Validating software versions (rpm or deb)... >> Beginning new cluster creation... backing up admintools.conf on 10.75.7.110 >> Creating or validating DB Admin user/group... Successful on hosts (3): 10.75.7.111 10.75.7.110 10.75.7.112 第 17 页 共 182 页 Provided DB Admin account details: user = dbadmin, group = verticadba, home = /home/dbadmin Creating group... Group already exists Validating group... Okay Creating user... User already exists Validating user... Okay >> Validating node and cluster prerequisites... System prerequisites passed. Threshold = WARN >> Establishing DB Admin SSH connectivity... Installing/Repairing SSH keys for dbadmin >> Setting up each node and modifying cluster... Creating Vertica Data Directory... Updating agent... Creating node node0001 definition for host 10.75.7.110 ... Done Creating node node0002 definition for host 10.75.7.111 ... Done Creating node node0003 definition for host 10.75.7.112 ... Done >> Sending new cluster configuration to all nodes... >> Completing installation... Running upgrade logic No spread upgrade required: /opt/vertica/config/vspread.conf not found on any node Installation complete. Please evaluate your hardware using Vertica's validation tools: https://my.vertica.com/docs/7.0.x/HTML/index.htm#cshid=VALSCRIPT To create a database: 1. Logout and login as dbadmin. (see note below) 2. Run /opt/vertica/bin/adminTools as dbadmin 3. Select Create Database from the Configuration Menu Note: Installation may have made configuration changes to dbadmin that do not take effect until the next session (logout and login). 第 18 页 共 182 页 To add or remove hosts, select Cluster Management from the Advanced Menu. 负载均衡配置 如果安装集群时使用了内网需要修改默认的 export 地址为 public ip 地址否则系统的 loadbalance 不可用: dbadmin=> CREATE NETWORK INTERFACE eth10 on v_dws_node0001 with '10.75.10.41'; CREATE NETWORK INTERFACE dbadmin=> CREATE NETWORK INTERFACE eth20 on v_dws_node0002 with '10.75.10.42'; dbadmin=> CREATE NETWORK INTERFACE eth30 on v_dws_node0003 with '10.75.10.43'; CREATE NETWORK INTERFACE dbadmin=> CREATE NETWORK INTERFACE eth40 on v_dws_node0004 with '10.75.10.44'; CREATE NETWORK INTERFACE dbadmin=> alter node v_dws_node0001 export on eth10; ALTER NODE dbadmin=> select * from nodes; node_name | node_id | node_state | node_address | export_address | is_ephemeral ----------------+-------------------+------------+--------------+----------------+-------------- v_dws_node0001 | 45035996273704980 | UP | 192.168.88.1 | 10.75.10.41 | f v_dws_node0002 | 45035996273718962 | UP | 192.168.88.2 | 10.75.10.42 | f v_dws_node0003 | 45035996273718966 | UP | 192.168.88.3 | 10.75.10.43 | f v_dws_node0004 | 45035996273718970 | UP | 192.168.88.4 | 10.75.10.44 | f dbadmin=> select * from network_interfaces; node_id | node_name | interface | ip_address | subnet | mask | broadcast_address -------------------+----------------+-----------+--------------+--------------+---------------+------------------- 45035996273704980 | v_dws_node0001 | lo | 127.0.0.1 | 127.0.0.0 | 255.0.0.0 | 127.0.0.1 45035996273704980 | v_dws_node0001 | eth0 | 10.75.10.41 | 10.75.10.0 | 255.255.255.0 | 10.75.10.255 45035996273704980 | v_dws_node0001 | eth1 | 192.168.88.1 | 192.168.88.0 | 255.255.255.0 | 192.168.88.255 45035996273718966 | v_dws_node0003 | lo | 127.0.0.1 | 127.0.0.0 | 255.0.0.0 | 127.0.0.1 45035996273718966 | v_dws_node0003 | eth0 | 10.75.10.43 | 10.75.10.0 | 255.255.255.0 | 10.75.10.255 45035996273718966 | v_dws_node0003 | eth1 | 192.168.88.3 | 192.168.88.0 | 255.255.255.0 | 192.168.88.255 45035996273718962 | v_dws_node0002 | lo | 127.0.0.1 | 127.0.0.0 | 255.0.0.0 | 127.0.0.1 45035996273718962 | v_dws_node0002 | eth0 | 10.75.10.42 | 10.75.10.0 | 255.255.255.0 | 10.75.10.255 45035996273718962 | v_dws_node0002 | eth1 | 192.168.88.2 | 192.168.88.0 | 255.255.255.0 | 192.168.88.255 45035996273718970 | v_dws_node0004 | lo | 127.0.0.1 | 127.0.0.0 | 255.0.0.0 | 127.0.0.1 45035996273718970 | v_dws_node0004 | eth0 | 10.75.10.44 | 10.75.10.0 | 255.255.255.0 | 10.75.10.255 45035996273718970 | v_dws_node0004 | eth1 | 192.168.88.4 | 192.168.88.0 | 255.255.255.0 | 192.168.88.255 (12 rows) 第 19 页 共 182 页 2.2 集群增加节点 增加节点的一般步骤是: A)备份数据库 B)配置新增节点 C)更新集群的配置 hosts 信息,增加新节点 D)把新增节点加入到数据库中 上面过程的第二步通过命令/opt/vertica/sbin/update_vertica --add-hosts host(s) --rpm package 来实现。其中第四步通过 [root@localhost vertica]# /opt/vertica/sbin/update_vertica -A 99.8.41.14 -r /home/vertica/vertica-7.0.1- 0.x86_64.RHEL5.rpm --failure-threshold=HALT Vertica Analytic Database 7.0.1-0 Installation Tool >> Validating options... Mapping hostnames in --add-hosts (-A) to addresses... >> Starting installation tasks. >> Getting system information for cluster (this may take a while)... Enter password for root@99.8.41.14 (3 attempts left): Default shell on nodes: 99.8.41.14 /bin/bash 99.8.41.6 /bin/bash >> Validating software versions (rpm or deb)... >> Beginning new cluster creation... backing up admintools.conf on 99.8.41.14 backing up admintools.conf on 99.8.41.6 >> Creating or validating DB Admin user/group... Successful on hosts (2): 99.8.41.14 99.8.41.6 Provided DB Admin account details: user = dbadmin, group = verticadba, home = /home/dbadmin Creating group... Group already exists Validating group... Okay Creating user... User already exists Validating user... Okay >> Validating node and cluster prerequisites... Failures during local (OS) configuration for verify-99.8.41.14.xml: HINT (S0151): https://my.vertica.com/docs/7.0.x/HTML/index.htm#cshid=S0151 These disks do not have known IO schedulers: '/dev/mapper/vg_localhost- lv_home' ('') = '', '/dev/mapper/vg_localhost-lv_root' ('') = '' HINT (S0305): https://my.vertica.com/docs/7.0.x/HTML/index.htm#cshid=S0305 TZ is unset for dbadmin. Consider updating .profile or .bashrc HINT (S0041): https://my.vertica.com/docs/7.0.x/HTML/index.htm#cshid=S0041 第 20 页 共 182 页 Could not find the following tools normally provided by the mcelog package: mcelog WARN (S0170): https://my.vertica.com/docs/7.0.x/HTML/index.htm#cshid=S0170 lvscan (LVM utility) indicates some active volumes. Failures during local (OS) configuration for verify-99.8.41.6.xml: HINT (S0151): https://my.vertica.com/docs/7.0.x/HTML/index.htm#cshid=S0151 These disks do not have known IO schedulers: '/dev/mapper/vg_localhost- lv_home' ('') = '', '/dev/mapper/vg_localhost-lv_root' ('') = '' HINT (S0305): https://my.vertica.com/docs/7.0.x/HTML/index.htm#cshid=S0305 TZ is unset for dbadmin. Consider updating .profile or .bashrc HINT (S0041): https://my.vertica.com/docs/7.0.x/HTML/index.htm#cshid=S0041 Could not find the following tools normally provided by the mcelog package: mcelog WARN (S0170): https://my.vertica.com/docs/7.0.x/HTML/index.htm#cshid=S0170 lvscan (LVM utility) indicates some active volumes. FAIL (S0020): https://my.vertica.com/docs/7.0.x/HTML/index.htm#cshid=S0020 Readahead size of (/dev/mapper/vg_localhost-lv_home,/dev/mapper /vg_localhost-lv_root) is too low for typical systems: 256 < 2048 Detected significant differences in the cluster: HINT: Differences in logical CPU count: verify-99.8.41.14.xml: 8 verify-99.8.41.6.xml: 1 HINT: Differences in RAM (kbytes): verify-99.8.41.14.xml: 8061840 verify-99.8.41.6.xml: 1923456 For more information, see https://my.vertica.com/docs/7.0.x/HTML/index.htm#cshid=CLREQ01 System prerequisites passed. Threshold = HALT >> Establishing DB Admin SSH connectivity... Installing/Repairing SSH keys for dbadmin >> Setting up each node and modifying cluster... Creating Vertica Data Directory... Updating agent... Creating node node0002 definition for host 99.8.41.14 ... Done >> Sending new cluster configuration to all nodes... >> Completing installation... Running upgrade logic No spread upgrade required: /opt/vertica/config/vspread.conf not found on any node Installation complete. Please evaluate your hardware using Vertica's validation tools: https://my.vertica.com/docs/7.0.x/HTML/index.htm#cshid=VALSCRIPT To create a database: 1. Logout and login as dbadmin. (see note below) 2. Run /opt/vertica/bin/adminTools as dbadmin 3. Select Create Database from the Configuration Menu Note: Installation may have made configuration changes to dbadmin 第 21 页 共 182 页 that do not take effect until the next session (logout and login). To add or remove hosts, select Cluster Management from the Advanced Menu. 2.3 集群删除节点 2.4 集群升级 由于 vertica5.x 之后版本进行升级会生成大量的事务字典信息,因此升级前需要预先评估剩余磁盘空间,一 般要大于 4 倍以上的 catalog 数据大小的空间为宜。 7.1.X 版本的 vertica 数据库,配置文件保存在数据库中,而非单独的 vertica.conf 文件,如果需要查询配 置信息可以通过系统表 CONFIGURATION_PARAMETERS 访问。 为了保证升级的正常和升级后应用正常运行,vertica 建议参考以下步骤进行升级: 1、 备份 vertica 数据库,备份方法参考 4.1 章节 2、 使用 admintools 工具停数据库。 参考命令: admintools -t stop_db -d dws -p password 3、 删除集群所有节点上的 vertica 依赖包,如 rpm -e vertica-R-lang 等。 4、 在所有节点上执行安装 vertica rpm 包的命令。 参考命令: rpm -Uvh vertica-7.1.1-0.x86_64.RHEL5.rpm 5、 执行 update_vertica 脚本进行升级,升级过程中参数和安装 vertica 的参数一样,除了不需要指定-- hosts/-s host_list 参数,因为 vertica 会自动识别已安装的集群。 [root@dws1 soft]# /opt/vertica/sbin/update_vertica --rpm /root/soft/vertica-7.1.1-0.x86_64.RHEL5.rpm --failure- threshold=HALT Vertica Analytic Database 7.1.1-0 Installation Tool 第 22 页 共 182 页 >> Validating options... >> Starting installation tasks. >> Getting system information for cluster (this may take a while)... Enter password for root@192.168.88.4 (3 attempts left): Default shell on nodes: 192.168.88.4 /bin/bash 192.168.88.3 /bin/bash 192.168.88.2 /bin/bash 192.168.88.1 /bin/bash >> Validating software versions (rpm or deb)... >> Beginning new cluster creation... backing up admintools.conf on 192.168.88.4 backing up admintools.conf on 192.168.88.3 backing up admintools.conf on 192.168.88.2 backing up admintools.conf on 192.168.88.1 >> Creating or validating DB Admin user/group... Successful on hosts (4): 192.168.88.4 192.168.88.3 192.168.88.2 192.168.88.1 Provided DB Admin account details: user = dbadmin, group = verticadba, home = /home/dbadmin Creating group... Group already exists Validating group... Okay Creating user... User already exists Validating user... Okay >> Validating node and cluster prerequisites... Prerequisites not fully met during local (OS) configuration for verify-192.168.88.1-4.xml: HINT (S0151): https://my.vertica.com/docs/7.1.x/HTML/index.htm#cshid=S0151 These disks do not have known IO schedulers: '/dev/mapper/VolGroup- lv_home' ('') = '', '/dev/mapper/VolGroup-lv_root' ('') = '' HINT (S0305): https://my.vertica.com/docs/7.1.x/HTML/index.htm#cshid=S0305 TZ is unset for dbadmin. Consider updating .profile or .bashrc WARN (S0170): https://my.vertica.com/docs/7.1.x/HTML/index.htm#cshid=S0170 lvscan (LVM utility) indicates some active volumes. FAIL (S0020): https://my.vertica.com/docs/7.1.x/HTML/index.htm#cshid=S0020 Readahead size of (/dev/mapper/VolGroup-lv_home,/dev/mapper/VolGroup- lv_root) is too low for typical systems: 256 < 2048 FAIL (S0030): https://my.vertica.com/docs/7.1.x/HTML/index.htm#cshid=S0030 ntpd process is not running: ['ntpd', 'ntp'] … Detected significant differences in the cluster: HINT: Differences in RAM (kbytes): verify-192.168.88.1.xml: 16465108 verify-192.168.88.4.xml: 16331988 verify-192.168.88.2.xml: 16465108 verify-192.168.88.3.xml: 16465108 For more information, see 第 23 页 共 182 页 https://my.vertica.com/docs/7.1.x/HTML/index.htm#cshid=CLREQ01 System prerequisites passed. Threshold = HALT >> Establishing DB Admin SSH connectivity... Installing/Repairing SSH keys for dbadmin >> Setting up each node and modifying cluster... Creating Vertica Data Directory... Updating agent... >> Sending new cluster configuration to all nodes... >> Completing installation... Running upgrade logic No spread upgrade required: /opt/vertica/config/vspread.conf not found on any node Installation complete. Please evaluate your hardware using Vertica's validation tools: https://my.vertica.com/docs/7.1.x/HTML/index.htm#cshid=VALSCRIPT To create a database: 1. Logout and login as dbadmin. (see note below) 2. Run /opt/vertica/bin/adminTools as dbadmin 3. Select Create Database from the Configuration Menu Note: Installation may have made configuration changes to dbadmin that do not take effect until the next session (logout and login). To add or remove hosts, select Cluster Management from the Advanced Menu. 6、 启动数据库,启动过程中会自动识别新版本软件和进行必要的数据字典升级。 参考命令: [dbadmin@dws1 ~]$ admintools -t start_db -d dws -p vertica Starting nodes: v_dws_node0001 (192.168.88.1) v_dws_node0002 (192.168.88.2) v_dws_node0003 (192.168.88.3) v_dws_node0004 (192.168.88.4) Starting Vertica on all nodes. Please wait, databases with large catalogs may take a while to initialize. Node Status: v_dws_node0001: (INITIALIZING) v_dws_node0002: (INITIALIZING) v_dws_node0003: (INITIALIZING) v_dws_node0004: (INITIALIZING) Node Status: v_dws_node0001: (INITIALIZING) v_dws_node0002: (INITIALIZING) v_dws_node0003: (INITIALIZING) v_dws_node0004: (INITIALIZING) Node Status: v_dws_node0001: (INITIALIZING) v_dws_node0002: (INITIALIZING) v_dws_node0003: (INITIALIZING) v_dws_node0004: (INITIALIZING) Node Status: v_dws_node0001: (UP) v_dws_node0002: (UP) v_dws_node0003: (UP) v_dws_node0004: (UP) Running upgrade hooks Database dws started successfully 7、 升级之后做一个全新的备份。 第 24 页 共 182 页 8、 安装之前删除的必要的软件包。 2.5 集群的 active standby 节点 Active standby 节点是一种特殊的节点,它作为一种备份节点随时准备替换失败的节点。Active standby 节点不包含数据,也不参与计算,一个普通的节点失败超过一定时间之后 active standby 节点会替换该失败节点, 此时会包含原来节点的数据和参与计算。 为了部署 active standby 节点,须首先设置参数 FailoverToStandbyAfter,如果可能 vertica 会在集群的 同一个 fault group 选择一个节点做 active standby,或者随机的选择一个可用节点。 数据库管理员可以手动的执行 alter node 命令替换一个失败的节点。你可以指定一个 active standby 节点 或者有 vertica 自动选取。自动替换时 vertica 选择和失败节点在同一个 fault group 的 standby 节点做切换, 如果 fault group 中没有 standby 节点则选择可用的 standby 节点。 2.5.1 创建 active standby 节点 可以在创建数据库的时候创建 active standby 节点,也可以在创建数据库之后。需要说明的是,创建 active standby 节点之后需要添加必要的存储位置。 以下是创建 active standby 的步骤: 1、 创建数据库,其中包含你希望作为 active standby 的节点。 2、 使用 vsql 登录到希望作为 active standby 的节点。 3、 使用 alter node 命令把该节点转化成 active standby 节点,该命令一旦执行该节点会 shutdown 并重 启为 active standby 节点。ALTER NODE node_name node_type[PERMANENT | EPHEMERAL | EXECUTE | STANDBY]。 另外对于一个已经存在的数据库创建 active standby 节点的方法是: 1、 添加一个新的节点到一个已经存在的数据库,但是不做 rebalance。 2、 使用 vsql 连接到该节点。 3、 使用 alter node 命令把永久节点转化成临时的中间节点,转化临时中间节点的步骤会清除节点上所有的 数据。ALTER NODE node_name node_type[PERMANENT | EPHEMERAL | EXECUTE | STANDBY] 4、 使用 alter node 命令把临时中间节点转化成 active standby 节点: ALTER NODE node_name node_type[PERMANENT | EPHEMERAL | EXECUTE | STANDBY]。 2.5.2 替换 active standby 节点 Vertica 可以实现自动切换和手动切换,对于自动切换的方式,需要提前配置参数 FailoverToStandbyAfter, 而手动方式可以通过以下步骤实现。 1、 通过 admintools 或者使用 vsql 连接到数据库。 2、 执行命令:ALTER NODE node-name REPLACE WITH standby-node-name; 第 25 页 共 182 页 2.5.3 反转 active standby 节点 如果一个 active standby 节点已经替换了失败节点,你可以反转这个 active standby 节点在节点级别或者 集群级别。如果一个已经 down 的节点无法执行操作,vertica 会忽略 reset 命令并保持 standby 节点的状 态。 以下是反转一个 standby 节点: 1、 通过 admintools 或者使用 vsql 连接到数据库。 2、 执行命令:ALTER NODE (node-name1)RESET; 以下是反转 active standby 的集群中所有节点: 1、 通过 admintools 或者使用 vsql 连接到数据库。 2、 执行命令:ALTER DATABASE (database-name)RESET STANDBY;. #Specify the DEFAULT network interface of the public network on node1, which is used for export. => ALTER NODE node1 EXPORT ON DEFAULT; #Replace Down Node with Active Standby Node Replace a down node, node1, with an active standby node. => ALTER NODE node1 REPLACE WITH standby1; #Restore Down Node Restore a down node, node1. When you reset the down node, HP Vertica automatically returns its replacement to standby status. => ALTER NODE node1 RESET; 3. Vertica 的管理和维护 3.1 增加磁盘 增加磁盘遵循以下步骤: #A)停止节点上的数据库实例 第 26 页 共 182 页 [dbadmin@V2 ~]$ admintools -t stop_node -s 10.75.7.111 *** Forcing host shutdown *** Sending host shutdown command to '10.75.7.111' #B)系统加盘,如果需要进行重启 [root@V2 ~]# fdisk -l Disk /dev/sda: 107.4 GB, 107374182400 bytes 255 heads, 63 sectors/track, 13054 cylinders Units = cylinders of 16065 * 512 = 8225280 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disk identifier: 0x00004733 Device Boot Start End Blocks Id System /dev/sda1 * 1 2611 20971520 83 Linux /dev/sda2 2611 3264 5242880 82 Linux swap / Solaris /dev/sda3 3264 13055 78642176 83 Linux Disk /dev/sdb: 107.4 GB, 107374182400 bytes====新加的未使用的盘 255 heads, 63 sectors/track, 13054 cylinders Units = cylinders of 16065 * 512 = 8225280 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disk identifier: 0x00000000 #C)分区、格式化、挂载到系统上 [root@V2 ~]# fdisk /dev/sdb Device contains neither a valid DOS partition table, nor Sun, SGI or OSF disklabel Building a new DOS disklabel with disk identifier 0x91176626. Changes will remain in memory only, until you decide to write them. After that, of course, the previous content won't be recoverable. Warning: invalid flag 0x0000 of partition table 4 will be corrected by w(rite) WARNING: DOS-compatible mode is deprecated. It's strongly recommended to switch off the mode (command 'c') and change display units to sectors (command 'u'). Command (m for help): Command (m for help): n Command action e extended p primary partition (1-4) p Partition number (1-4): 1 First cylinder (1-13054, default 1): Using default value 1 第 27 页 共 182 页 Last cylinder, +cylinders or +size{K,M,G} (1-13054, default 13054): Using default value 13054 Command (m for help): w The partition table has been altered! Calling ioctl() to re-read partition table. Syncing disks. D)新建目录,如果集群都要加盘,那么路径最好一致 [root@V2 ~]# mkdir /u01 [root@V2 ~]# mkfs.ext4 /dev/sdb1 mke2fs 1.41.12 (17-May-2010) Filesystem label= OS type: Linux Block size=4096 (log=2) Fragment size=4096 (log=2) Stride=0 blocks, Stripe width=0 blocks 6553600 inodes, 26214055 blocks 1310702 blocks (5.00%) reserved for the super user First data block=0 Maximum filesystem blocks=4294967296 800 block groups 32768 blocks per group, 32768 fragments per group 8192 inodes per group Superblock backups stored on blocks: 32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208, 4096000, 7962624, 11239424, 20480000, 23887872 Writing inode tables: done Creating journal (32768 blocks): done Writing superblocks and filesystem accounting information: done This filesystem will be automatically checked every 32 mounts or 180 days, whichever comes first. Use tune2fs -c or -i to override. [root@V2 ~]# mount /dev/sdb1 /u01 #E)如果之前做过重启,需要重启节点的数据库实例 [dbadmin@V2 ~]$ admintools -t restart_node -d vertica -s 10.75.7.111 -p 123456 *** Restarting nodes for database vertica *** restart host 10.75.7.111 with catalog v_vertica_node0002_catalog issuing multi-node restart Starting nodes: v_vertica_node0002 (10.75.7.111) Starting Vertica on all nodes. Please wait, databases with large catalogs may take a while 第 28 页 共 182 页 to initialize. Node Status: v_vertica_node0002: (INITIALIZING) Node Status: v_vertica_node0002: (INITIALIZING) Node Status: v_vertica_node0002: (RECOVERING) Node Status: v_vertica_node0002: (UP) Restart Nodes result: 1 #F)连接数据库通过 ADD_LOCATION 进行加盘 dbadmin=> SELECT ADD_LOCATION('/u01/data/','v_vertica_node0002', 'USER'); ADD_LOCATION ------------------ /u01/data added. (1 row) #G)检查是否已正确加入数据库 dbadmin=> select * from storage_locations where node_name='v_vertica_node0002'; -[ RECORD 1 ]--+--------------------------------------------------- location_id | 45035996273718968 node_name | v_vertica_node0002 location_path | /home/dbadmin/data/vertica/v_vertica_node0002_data location_usage | DATA,TEMP is_retired | f location_label | rank | 0 throughput | 0 latency | 0 -[ RECORD 2 ]--+--------------------------------------------------- location_id | 49539595901305832 node_name | v_vertica_node0002 location_path | /u01/data location_usage | USER is_retired | f location_label | rank | 0 throughput | 0 latency | 0 3.2 替换坏盘 A)替换掉损坏的磁盘,新建 data 和 catalog 目录 第 29 页 共 182 页 B)把配置文件(vertica.conf) 分发到新的主机上 C)重启新节点的数据库实例 3.3 回收磁盘空间 空间的回收可以通过清空 deleted 记录、rebuilt 表、删除分区等方式实现。 3.3.1 重建表的过程 1. Create a new table. 2. Create projections for the new table. 3. Populate the new table using INSERT ... SELECT to copy the desired table from the old table. 4. Drop the old table and its projections. 5. Use ALTER TABLE ... RENAME to give the new table the name of the old table. 说明: 1、表和 Projection 没有直接关联,不会因为 rename 导致失效,表的 ID 和 Projection 关联,并且不会因为 rename 表发生变化 2、必须有足够的磁盘空间保存新表和旧表的全部数据和 Projection,如果空间紧张可以考虑删除部分旧表的 Projection,但至少要保留一个或者一对 buddy Projection 以保障 ksafe 3.4 存储位置 如要和 Oracle 数据库相比的话,vertica 的存储位置相当于 Oracle 数据库的表空间。Vertica 建议在集群中 的每个节点都创建相同路径的存储位置,创建好磁盘目录之后就可以通过 ADD_LOCATION()增加为数据库的一 个存储位置。 每次进行 DML 或者数据加载的过程中,新的数据都会先进入 WOS,然后依据一定的间隔移动到磁盘上的存 储位置,即 ROS。如果要存储的数据未指定存储策略,则使用当前可用的未加存储策略的存储位置,并使用默认 的存储机制。如果数据有设置存储策略,则数据会被存放在存储策略指定的加标签的存储位置。 创建存储位置主要有以下目的:  隔离执行引擎的数据文件和临时文件  创建带标签的存储位置以使用存储策略  创建某种访问模式或速度的存储位置 第 30 页 共 182 页  为某些用户和组创建存储位置 使用存储位置需要进行一些规划,这些规划主要是:  检查存储位置是否有合适的读写权限且目录为空  如果使用带标签的存储位置要设计好存储策略和存储位置标签  决定要存放数据的类型,存储位置有:data-存放数据包括临时表数据文件;temp- 存放 sort, group by, join 等产生的临时文件;DATA,TEMP-数据和临时文件;USER-非 DBA 用户可以 访问的存储位置 不同类型的存储位置有各自的一些特点,相互之间存在一些限制。如带标签的存储位置只能存放数据文件; 带标签的存储位置不能转换成 temp 和 data、或者 temp 类型的存储位置;user 类型的存储位置只能存放数据 文件;user 类型的存储位置不可以和其它类型的存储位置进行转换。 如果需要修改存储位置的类型,可以使用函数 ALTER_LOCATION_USE 进行改变存储位置的类型。修改存 储位置类型时要保证每个节点至少一个 data、temp 类型的存储位置。 Alter use from To store only Has this effect Temp 和 data files、Data only Temp files ATM 自动把数据 mergeout 出去,以后只存储临时数据 Temp 和 data files、Temp only Data files 继续运行所有使用临时文件的 SQL 语句,后续的 SQL 只往 该位置存数据文件 可以给存储位置设置存储标签,修改已存在的存储标签,删除存储标签。如果给已存在数据的存储位置设置 存储标签之后指定了存储策略,那么原有数据不满足存储策略的情况下数据会被 ATM 移动到其它地方。如果要 删除存储位置的标签时,如果该存储位置已指定了存储策略而且该存储位置是在这种策略下最后一个存储位置, 则无法删除。 Alter use from To store only Has this effect No name New label 可以在存储策略中使用新的存储标签名 Existing name New name 可以在存储策略中使用新的存储标签名,如果原有存储标签正在存储策略中 使用,则无法修改 Existing name No name 存储策略不能使用无标签的存储位置,如果原有存储标签正在存储策略中使 用,则无法修改 第 31 页 共 182 页 3.5 存储策略 每次加载数据或者进行 DML 新数据都会按照一定的间隔由内存(WOS)移动到磁盘(ROS),如果对象没 有被指定存储策略,系统使用默认的存储策略。 可以通过 SET_OBJECT_STORAGE_POLICY 过程给对象设定存储策略,如对 cell_11 表设定存储策略的 过程如下: #三个节点同时加磁盘 dbadmin=> SELECT ADD_LOCATION ('/u01/data/' , '' , 'DATA'); ADD_LOCATION ------------------ /u01/data added. (1 row) #设置标签 dbadmin=> select alter_location_label('/u01/data','', 'LARGETABLE'); alter_location_label -------------------------- /u01/data label changed. (1 row) #设置对象的存储策略 dbadmin=> select set_object_storage_policy('cell_11', 'LARGETABLE', 'true'); set_object_storage_policy ------------------------------------------------------------------------------------ Object storage policy set. Task: moving storages (Table: public.cell_11) (Projection: public.cell_11_b0) (Table: public.cell_11) (Projection: public.cell_11_b1) (1 row) dbadmin=> select set_object_storage_policy('ods_ucm.cell_11', 'LARGETABLE', 'true'); set_object_storage_policy ------------------------------------------------------------------------------------ Object storage policy set. Task: moving storages (Table: ods_ucm.cell_11) (Projection: ods_ucm.cell_11_b0) (Table: ods_ucm.cell_11) (Projection: ods_ucm.cell_11_b1) (1 row) 一旦给对象设置了存储策略之后,vertica 会把存储策略所指定的位置作为该对象默认的存储位置。设置存储 策略可以让我们来区分磁盘对应的数据存放,比如把重要数据存放在较快的磁盘上。需要说明的是存储策略只对 DATA 类型的磁盘有效,不能包含 temp 文件,也不能使 user 类型的存储位置。 第 32 页 共 182 页 可以给任何数据库对象创建存储策略,如数据库、模式、表、分区等,每次数据加载和更新的时候,vertica 都会去检查对象是否有存储策略,如果有就使用标签的存储位置,如果没有存储策略,则可用的存储位置中选择 一个使用默认的存储机制存放,如果所有的存储位置都是带标签的,vertica 选择其中一个使用。 并不要求对所有的对象都创建存储策略,一个存储策略可以包含若干离散对象。 我们可以创建基于磁盘性能的存储策略,磁盘的性能可以基于我们采购时的分类,也可以通过检验 IO 时间来 测量磁盘的性能。Vertica 使用函数 MEASURE_LOCATION_PERFORMANCE 或者 opt/vertica/bin/vertica –m 可以测量磁盘的性能,vertica 测量磁盘的性能基于以下计算公式: IO time = time to read/write 1MB + time to seek = 1/throughput + 1/Latency 给存储划分不同的级别和优先级,数据库级别是最高的级别,分区被认为是对象的最小级别,级别越高对应 的存储位置优先级越低,反之级别越低对应的存储位置优先级越高。 对象 存储级别 存储策略 存储优先级 存储位置标签 Sales (database) Highest YES Lower STANDARD Region (schema) Medium NO Medium N/A Income (table) Lower YES Higher/highest FAST Month (partitions) Lowest NO Highest N/A 上表中对数据库和表级别对象设置了存储策略,他们对应的默认存储位置的标签分别是 STANDARD 和 FAST。当 TM 进行 mergeout 或者 moveout 操作时,表数据有最高优先级,TM 移动数据从 ROS 到 WOS 到 FAST 标签的存储位置。模式上数据的改变优先级会略低于表上的数据。 第 33 页 共 182 页 4. Vertica 数据库备份恢复 4.1 Vertica 备份 Vertica 的备份可以在本机实施,也可以通过配置备份主机在集群外其它机器进行,本例以在备份主机实施 备份的方式进行。Vertica 的备份又可以分为全备份(FULL BACKUP)和增量备份(INCREMENTAL BACKUP)。在备份主机进行备份的方式,备份主机和 vertica 集群需要在同一个网段,以保障网络的带宽能够 满足。 4.1.1 Vertica 备份环境准备 #检查 vertica 集群和备份主机之间的 python 和 rsync 的版本是否一致: 集群 node3 [dbadmin@V3 ~]$ python --version Python 2.6.6 [dbadmin@V3 ~]$ rsync --version |head -1 rsync version 3.0.6 protocol version 30 backup host: [dbadmin@DWS backup]$ python --version Python 2.6.6 [dbadmin@DWS backup]$ rsync --version |head -1 rsync version 3.0.6 protocol version 30 #配置 vertica 集群和备份主机之间的 ssh 信任关系: 参考 1.11 章节方法 4.1.2 Vertica 备份配置文件 以 dbadmin 用户登录并执行如下命令: [dbadmin@V3 ~]$ /opt/vertica/bin/vbr.py --setupconfig Snapshot name (backup_snapshot): full_lizy_20140729 Backup vertica configurations? (n) [y/n]: y Number of restore points (1): 3 Specify objects (no default): Vertica user name (dbadmin): 第 34 页 共 182 页 Save password to avoid runtime prompt? (n) [y/n]: y Password to save in vbr config file (no default): Node v_vertica_node0001 Backup host name (no default): 10.75.10.4 Backup directory (no default): /home/dbadmin/backup Node v_vertica_node0002 Backup host name (no default): 10.75.10.4 Backup directory (no default): /home/dbadmin/backup Node v_vertica_node0003 Backup host name (no default): 10.75.10.4 Backup directory (no default): /home/dbadmin/backup Config file name (full_lizy_20140729.ini): Change advanced settings? (n) [y/n]: y Temp directory (/tmp/vbr): Number of times to retry (2): Seconds between retry attempts (1): Encrypt data during transmission? (n) [y/n]: Use checksum for data integrity (not file data and size)? (n) [y/n]: Port number for rsync daemon (50000): Transfer bandwidth limit in KBps or 0 for unlimited (0): Saved vbr configuration to full_lizy_20140729.ini. 以上命令完成之后生成的配置文件如下: 第 35 页 共 182 页 [dbadmin@V3 ~]$ more full_lizy_20140729.ini [Misc] snapshotName = full_lizy_20140729 verticaConfig = True restorePointLimit = 3 tempDir = /tmp/vbr retryCount = 2 retryDelay = 1 [Database] dbName = vertica dbUser = dbadmin [Transmission] encrypt = False checksum = False port_rsync = 50000 bwlimit = 0 [Mapping] v_vertica_node0001 = 10.75.10.4:/home/dbadmin/backup v_vertica_node0002 = 10.75.10.4:/home/dbadmin/backup v_vertica_node0003 = 10.75.10.4:/home/dbadmin/backup 4.1.3 Vertica 全备份 ##执行备份脚本 [dbadmin@V3 ~]$ vbr.py --task backup --config-file full_lizy_20140729.ini Preparing... Found Database port: 5433 Password: Password: Password: Copying... [==================================================] 100% All child processes terminated successfully. Committing changes on all backup sites... backup done! Password: Password: Password: ##检查每个节点的数据量 第 36 页 共 182 页 dbadmin=> select node_name,sum(used_bytes) as size_in_bytes from v_monitor.storage_containers group by node_name; node_name | size_in_bytes --------------------+--------------- v_vertica_node0001 | 194516863 v_vertica_node0002 | 194325236 v_vertica_node0003 | 194698074 (3 rows) #全量备份之后的目录结构 [dbadmin@V3 ~]$ tree -L 6 -d backup backup ├── v_vertica_node0001 │ └── full_lizy_20140729 │ └── home │ └── dbadmin │ └── vertica │ ├── v_vertica_node0001_catalog │ └── v_vertica_node0001_data ├── v_vertica_node0002 │ └── full_lizy_20140729 │ └── home │ └── dbadmin │ └── vertica │ ├── v_vertica_node0002_catalog │ └── v_vertica_node0002_data └── v_vertica_node0003 └── full_lizy_20140729 └── home └── dbadmin └── vertica ├── v_vertica_node0003_catalog └── v_vertica_node0003_data 21 directories 4.1.4 Vertica 增量备份 #再次执行上次相同的全备命令即可进行增量备份 [dbadmin@V3 ~]$ vbr.py --task backup --config-file full_lizy_20140729.ini Preparing... Found Database port: 5433 Password: Password: 第 37 页 共 182 页 Password: Copying... [==================================================] 100% All child processes terminated successfully. Committing changes on all backup sites... backup done! Password: Password: Password: #增量备份之后的目录结构 [dbadmin@V3 ~]$ tree -L 6 -d backup backup ├── v_vertica_node0001 │ ├── full_lizy_20140729 │ │ └── home │ │ └── dbadmin │ │ └── vertica │ │ ├── v_vertica_node0001_catalog │ │ └── v_vertica_node0001_data │ └── full_lizy_20140729_archive20140729_163929 │ └── home │ └── dbadmin │ └── vertica │ ├── v_vertica_node0001_catalog │ └── v_vertica_node0001_data ├── v_vertica_node0002 │ ├── full_lizy_20140729 │ │ └── home │ │ └── dbadmin │ │ └── vertica │ │ ├── v_vertica_node0002_catalog │ │ └── v_vertica_node0002_data │ └── full_lizy_20140729_archive20140729_163929 │ └── home │ └── dbadmin │ └── vertica │ ├── v_vertica_node0002_catalog │ └── v_vertica_node0002_data └── v_vertica_node0003 ├── full_lizy_20140729 │ └── home │ └── dbadmin │ └── vertica 第 38 页 共 182 页 │ ├── v_vertica_node0003_catalog │ └── v_vertica_node0003_data └── full_lizy_20140729_archive20140729_163929 └── home └── dbadmin └── vertica ├── v_vertica_node0003_catalog └── v_vertica_node0003_data 39 directories #需要说明的是在进行增量备份的时候 vertica 根据参数文件的 restorePointLimit 控制增量备份集的数量,并自 动删除旧的备份集 #进行三次备份之后的目录结构,restorePointLimit=3 [dbadmin@V3 ~]$ tree -L 6 -d backup backup ├── v_vertica_node0001 │ ├── full_lizy_20140729 │ │ └── home │ │ └── dbadmin │ │ └── vertica │ │ ├── v_vertica_node0001_catalog │ │ └── v_vertica_node0001_data │ ├── full_lizy_20140729_archive20140729_163929 │ │ └── home │ │ └── dbadmin │ │ └── vertica │ │ ├── v_vertica_node0001_catalog │ │ └── v_vertica_node0001_data │ ├── full_lizy_20140729_archive20140729_164338 │ │ └── home │ │ └── dbadmin │ │ └── vertica │ │ ├── v_vertica_node0001_catalog │ │ └── v_vertica_node0001_data │ └── full_lizy_20140729_archive20140729_165045 │ └── home │ └── dbadmin │ └── vertica │ ├── v_vertica_node0001_catalog │ └── v_vertica_node0001_data ├── v_vertica_node0002 │ ├── full_lizy_20140729 │ │ └── home 第 39 页 共 182 页 │ │ └── dbadmin │ │ └── vertica │ │ ├── v_vertica_node0002_catalog │ │ └── v_vertica_node0002_data │ ├── full_lizy_20140729_archive20140729_163929 │ │ └── home │ │ └── dbadmin │ │ └── vertica │ │ ├── v_vertica_node0002_catalog │ │ └── v_vertica_node0002_data │ ├── full_lizy_20140729_archive20140729_164338 │ │ └── home │ │ └── dbadmin │ │ └── vertica │ │ ├── v_vertica_node0002_catalog │ │ └── v_vertica_node0002_data │ └── full_lizy_20140729_archive20140729_165045 │ └── home │ └── dbadmin │ └── vertica │ ├── v_vertica_node0002_catalog │ └── v_vertica_node0002_data └── v_vertica_node0003 ├── full_lizy_20140729 │ └── home │ └── dbadmin │ └── vertica │ ├── v_vertica_node0003_catalog │ └── v_vertica_node0003_data ├── full_lizy_20140729_archive20140729_163929 │ └── home │ └── dbadmin │ └── vertica │ ├── v_vertica_node0003_catalog │ └── v_vertica_node0003_data ├── full_lizy_20140729_archive20140729_164338 │ └── home │ └── dbadmin │ └── vertica │ ├── v_vertica_node0003_catalog │ └── v_vertica_node0003_data └── full_lizy_20140729_archive20140729_165045 └── home └── dbadmin 第 40 页 共 182 页 └── vertica ├── v_vertica_node0003_catalog └── v_vertica_node0003_data 75 directories #进行四次备份之后的目录结构,可以发现备份集 full_lizy_20140729_archive20140729_163929 已被删除 [dbadmin@V3 ~]$ tree -L 6 -d backup backup ├── v_vertica_node0001 │ ├── full_lizy_20140729 │ │ └── home │ │ └── dbadmin │ │ └── vertica │ │ ├── v_vertica_node0001_catalog │ │ └── v_vertica_node0001_data │ ├── full_lizy_20140729_archive20140729_164338 │ │ └── home │ │ └── dbadmin │ │ └── vertica │ │ ├── v_vertica_node0001_catalog │ │ └── v_vertica_node0001_data │ ├── full_lizy_20140729_archive20140729_165045 │ │ └── home │ │ └── dbadmin │ │ └── vertica │ │ ├── v_vertica_node0001_catalog │ │ └── v_vertica_node0001_data │ └── full_lizy_20140729_archive20140729_165149 │ └── home │ └── dbadmin │ └── vertica │ ├── v_vertica_node0001_catalog │ └── v_vertica_node0001_data ├── v_vertica_node0002 │ ├── full_lizy_20140729 │ │ └── home │ │ └── dbadmin │ │ └── vertica │ │ ├── v_vertica_node0002_catalog │ │ └── v_vertica_node0002_data │ ├── full_lizy_20140729_archive20140729_164338 │ │ └── home │ │ └── dbadmin │ │ └── vertica 第 41 页 共 182 页 │ │ ├── v_vertica_node0002_catalog │ │ └── v_vertica_node0002_data │ ├── full_lizy_20140729_archive20140729_165045 │ │ └── home │ │ └── dbadmin │ │ └── vertica │ │ ├── v_vertica_node0002_catalog │ │ └── v_vertica_node0002_data │ └── full_lizy_20140729_archive20140729_165149 │ └── home │ └── dbadmin │ └── vertica │ ├── v_vertica_node0002_catalog │ └── v_vertica_node0002_data └── v_vertica_node0003 ├── full_lizy_20140729 │ └── home │ └── dbadmin │ └── vertica │ ├── v_vertica_node0003_catalog │ └── v_vertica_node0003_data ├── full_lizy_20140729_archive20140729_164338 │ └── home │ └── dbadmin │ └── vertica │ ├── v_vertica_node0003_catalog │ └── v_vertica_node0003_data ├── full_lizy_20140729_archive20140729_165045 │ └── home │ └── dbadmin │ └── vertica │ ├── v_vertica_node0003_catalog │ └── v_vertica_node0003_data └── full_lizy_20140729_archive20140729_165149 └── home └── dbadmin └── vertica ├── v_vertica_node0003_catalog └── v_vertica_node0003_data 75 directories 第 42 页 共 182 页 4.1.5 Vertica 对象级备份 说明: 1、 对象级备份如果同一个备份集中有多个对象,恢复时会一并恢复 2、 对于有多个对象的系统,对象级备份可以在并发在多个备份机进行 #配置对象备份的参数文件 [dbadmin@V3 ~]$ /opt/vertica/bin/vbr.py --setupconfig Snapshot name (backup_snapshot): obj_lizy_20140729 Backup vertica configurations? (n) [y/n]: y Number of restore points (1): 3 Specify objects (no default): lizy,ods_ucm Vertica user name (dbadmin): Save password to avoid runtime prompt? (n) [y/n]: y Password to save in vbr config file (no default):123456 --dbadmin 密码不回显 Node v_vertica_node0001 Backup host name (no default): 10.75.7.112 Backup directory (no default): /home/dbadmin/backup Node v_vertica_node0002 Backup host name (no default): 10.75.7.112 Backup directory (no default): /home/dbadmin/backup Node v_vertica_node0003 Backup host name (no default): 10.75.7.112 Backup directory (no default): /home/dbadmin/backup Config file name (obj_lizy_20140729.ini): Change advanced settings? (n) [y/n]: Saved vbr configuration to obj_lizy_20140729.ini. #参数文件内容如下: [dbadmin@V3 ~]$ cat obj_lizy_20140729.ini [Misc] snapshotName = obj_lizy_20140729 verticaConfig = True restorePointLimit = 3 objects = lizy,ods_ucm [Database] dbName = vertica dbUser = dbadmin 第 43 页 共 182 页 dbPassword = 123456 [Transmission] [Mapping] v_vertica_node0001 = 10.75.7.112:/home/dbadmin/backup v_vertica_node0002 = 10.75.7.112:/home/dbadmin/backup v_vertica_node0003 = 10.75.7.112:/home/dbadmin/backup #对象级备份 [dbadmin@V3 ~]$ vbr.py --task backup --config-file obj_lizy_20140729.ini Preparing... Found Database port: 5433 Copying... [==================================================] 100% All child processes terminated successfully. Committing changes on all backup sites... backup done! 4.1.6 Vertica HardLinkLocal 备份 HardLinkLocal 备份用于将数据备份到磁带上,或者从磁带恢复,一般 vertica 建议先进行全备份或者对象 级备份后再实施 HardLinkLocal 备份。 注意: 1、 如果在备份的时候在参数文件的指定了 hardLinkLocal=True,即使用 HardLinkLocal 备份,此时如果备份 目录在不同的节点上,vertica 会告警并退出。 2、 如果 HardLinkLocal 备份,备份目录在 vertica 集群的节点上,但是和 data、catalog 不同目录,vertica 会告警并继续备份。 #step 1 先创建备份参数文件 /opt/vertica/bin/vbr.py --setupconfig [dbadmin@V3 ~]$ /opt/vertica/bin/vbr.py --setupconfig Snapshot name (backup_snapshot): full_lizy_hll_20140729 Backup vertica configurations? (n) [y/n]: y Number of restore points (1): 3 Specify objects (no default): Vertica user name (dbadmin): Save password to avoid runtime prompt? (n) [y/n]: y 第 44 页 共 182 页 Password to save in vbr config file (no default): Node v_vertica_node0001 Backup host name (no default): 10.75.7.110 Backup directory (no default): /home/dbadmin/backup Node v_vertica_node0002 Backup host name (no default): 10.75.7.111 Backup directory (no default): /home/dbadmin/backup Node v_vertica_node0003 Backup host name (no default): 10.75.7.112 Backup directory (no default): /home/dbadmin/backup Config file name (full_lizy_hll_20140729.ini): Change advanced settings? (n) [y/n]: n Saved vbr configuration to full_lizy_hll_20140729.ini. #step 2 编辑备份参数文件,在[Transmission]部分增加 hardLinkLocal=True 参数 [dbadmin@V3 ~]$ cat full_lizy_hll_20140729.ini [Misc] snapshotName = full_lizy_hll_20140729 verticaConfig = True restorePointLimit = 3 [Database] dbName = vertica dbUser = dbadmin dbPassword = 123456 [Transmission] hardLinkLocal=True [Mapping] v_vertica_node0001 = 10.75.7.110:/home/dbadmin/backup v_vertica_node0002 = 10.75.7.111:/home/dbadmin/backup v_vertica_node0003 = 10.75.7.112:/home/dbadmin/backup #step 3 实施 hardLinkLocal 备份 [dbadmin@V3 ~]$ /opt/vertica/bin/vbr.py --task backup --config-file full_lizy_hll_20140729.ini Preparing... Found Database port: 5433 Copying... [==================================================] 100% All child processes terminated successfully. Committing changes on all backup sites... backup done! 第 45 页 共 182 页 #step 4 通过 copy 或其它方式把 HLL 备份目录复制到其它介质 #step 5 恢复时把备份 copy 到原来目录 #step 6 执行恢复 /opt/vertica/bin/vbr.py --task restore --config-file full_lizy_hll_20140729.ini 4.1.7 Vertica 备份查询 #Method 1 vbr.py listbackup [dbadmin@V3 ~]$ /opt/vertica/bin/vbr.py --task listbackup --config-file full_lizy_20140729.ini Found 4 backup(s) with given config file full_lizy_20140729.ini. backup epoch objects hosts(nodes) full_lizy_20140729_20140729_165335 345 v_vertica_node0001(10.75.7.112), v_vertica_node0002(10.75.7.112), v_vertica_node0003(10.75.7.112) full_lizy_20140729_archive20140729_165149 345 v_vertica_node0001(10.75.7.112), v_vertica_node0002(10.75.7.112), v_vertica_node0003(10.75.7.112) full_lizy_20140729_archive20140729_165045 345 v_vertica_node0001(10.75.7.112), v_vertica_node0002(10.75.7.112), v_vertica_node0003(10.75.7.112) full_lizy_20140729_archive20140729_164338 345 v_vertica_node0001(10.75.7.112), v_vertica_node0002(10.75.7.112), v_vertica_node0003(10.75.7.112) [dbadmin@V3 ~]$ /opt/vertica/bin/vbr.py --task listbackup --config-file full_lizy_hll_20140729.ini Found 1 backup(s) with given config file full_lizy_hll_20140729.ini. backup epoch objects hosts(nodes) full_lizy_hll_20140729_20140730_100810 350 v_vertica_node0001(10.75.7.110), v_vertica_node0002(10.75.7.111), v_vertica_node0003(10.75.7.112) #Method 2 vbr.py 在执行过程中 database_snapshots 视图可以监控状态 dbadmin=> select * from database_snapshots; -[ RECORD 1 ]---------+----------------------- node_name | v_vertica_node0001 snapshot_name | full_lizy_20140729 is_durable_snapshot | t total_size_bytes | 199394447 storage_cost_bytes | 1402135 acquisition_timestamp | 2014-07-30 10:42:41+08 -[ RECORD 2 ]---------+----------------------- node_name | v_vertica_node0002 snapshot_name | full_lizy_20140729 第 46 页 共 182 页 is_durable_snapshot | t total_size_bytes | 199278666 storage_cost_bytes | 1438519 acquisition_timestamp | 2014-07-30 10:42:41+08 -[ RECORD 3 ]---------+----------------------- node_name | v_vertica_node0003 snapshot_name | full_lizy_20140729 is_durable_snapshot | t total_size_bytes | 199296942 storage_cost_bytes | 1265729 acquisition_timestamp | 2014-07-30 10:42:41+08 #Method 3 历史备份可以通过视图 database_backups 查询 dbadmin=> select * from database_backups; -[ RECORD 1 ]----+------------------------------ backup_timestamp | 2014-07-29 12:54:04.726062+08 node_name | v_vertica_node0003 snapshot_name | full_lizy_20140729 backup_epoch | 345 node_count | 3 objects | -[ RECORD 2 ]----+------------------------------ backup_timestamp | 2014-07-29 16:16:23.096018+08 node_name | v_vertica_node0003 snapshot_name | full_lizy_20140729 backup_epoch | 345 node_count | 3 objects | -[ RECORD 3 ]----+------------------------------ backup_timestamp | 2014-07-29 16:38:35.657292+08 node_name | v_vertica_node0003 snapshot_name | full_lizy_20140729 backup_epoch | 345 node_count | 3 objects | 4.2 Vertica 恢复 第 47 页 共 182 页 4.2.1 Vertica 全量恢复 restore 时数据库必须是 down 的状态,up 状态的数据库无法进行恢复的,恢复时使用备份的脚本和备份文 件进行恢复。 需要说明的是全库恢复是把数据库恢复到某一备份时间的状态,在该备份之后数据库发生了的变化会丢失。 #案例 1 某一个节点的数据库数据文件被删除时的恢复,使用备份的参数文件和备份数据进行恢复,恢复后数据库正常启动 [dbadmin@V3 ~]$ vbr.py --task restore --config-file full_lizy_20140729.ini Preparing... Found Database port: 5433 Copying... [==================================================] 100% All child processes terminated successfully. restore done! [dbadmin@V3 ~]$ admintools -t start_db -d vertica -p 123456 Starting nodes: v_vertica_node0003 (10.75.7.112) v_vertica_node0001 (10.75.7.110) v_vertica_node0002 (10.75.7.111) Starting Vertica on all nodes. Please wait, databases with large catalogs may take a while to initialize. Node Status: v_vertica_node0001: (INITIALIZING) v_vertica_node0002: (INITIALIZING) v_vertica_node0003: (INITIALIZING) Node Status: v_vertica_node0001: (INITIALIZING) v_vertica_node0002: (INITIALIZING) v_vertica_node0003: (INITIALIZING) Node Status: v_vertica_node0001: (INITIALIZING) v_vertica_node0002: (INITIALIZING) v_vertica_node0003: (INITIALIZING) Node Status: v_vertica_node0001: (UP) v_vertica_node0002: (UP) v_vertica_node0003: (UP) Database vertica started successfully dbadmin=> select * from nodes; node_name | node_id | node_state | node_address | export_address | catalog_path | is_ephemeral --------------------+-------------------+------------+--------------+----------------+---------- --------------------------------------------------------+-------------- v_vertica_node0003 | 45035996273704980 | UP | 10.75.7.112 | 10.75.7.112 | /home/dbadmin/catalog/vertica/v_vertica_node0003_catalog/Catalog | f v_vertica_node0001 | 45035996273718962 | UP | 10.75.7.110 | 10.75.7.110 | /home/dbadmin/catalog/vertica/v_vertica_node0001_catalog/Catalog | f v_vertica_node0002 | 45035996273718966 | UP | 10.75.7.111 | 10.75.7.111 | /home/dbadmin/catalog/vertica/v_vertica_node0002_catalog/Catalog | f (3 rows) dbadmin=> select count(*) from tables; count ------- 105 (1 row) #案例 2,全量恢复时如果数据库重建过,则新建的数据库名称、catalog、data 文件路径要一致否则恢复脚本显示完成,但是数 据并未实际恢复 #重新建库时脚本和原来不同,最初使用 admintools 图形界面,第二次使用 admintools -t create_db -d vertica -s 第 48 页 共 182 页 10.75.7.110,10.75.7.111,10.75.7.112 -c /home/dbadmin/catalog -D /home/dbadmin/data -p 123456 #恢复时报错 [dbadmin@V3 ~]$ vbr.py --task restore --config-file full_lizy_20140729.ini Preparing... Found Database port: 5433 Topology changed after backup; cannot restore. restore failed! #重建成和原来一样的空数据库后可以正常恢复 [dbadmin@V3 ~]$ vbr.py --task restore --config-file full_lizy_20140729.ini Preparing... Found Database port: 5433 Copying... [==================================================] 100% All child processes terminated successfully. restore done! dbadmin=> select count(*) from tables; count ------- 105 (1 row) dbadmin=> select node_name,sum(used_bytes) as size_in_bytes from v_monitor.storage_containers group by node_name; node_name | size_in_bytes --------------------+--------------- v_vertica_node0002 | 159227872 v_vertica_node0003 | 159236568 v_vertica_node0001 | 159381288 (3 rows) 4.2.2 Vertica 对象恢复 对象备份之后如果新增了节点,对象恢复能够正常进行并把数据恢复到新节点上,但是如果对象备份之后删 除了节点或者节点改名、改 IP 都无法正常恢复。 #如果尝试从一个全库的备份区恢复对象会报错 dbadmin=> drop schema lizy cascade; DROP SCHEMA dbadmin=> drop schema ods_ucm cascade; DROP SCHEMA dbadmin=> \dn List of schemas Name | Owner | Comment -------------+---------+--------- v_internal | dbadmin | v_catalog | dbadmin | v_monitor | dbadmin | public | dbadmin | schema_test | dbadmin | 第 49 页 共 182 页 DEB_CIF | dbadmin | etl_cfg | dbadmin | stg_mic | dbadmin | ods_mic | dbadmin | SYSIBM | dbadmin | dwa_fat | dbadmin | stg_cif | dbadmin | ods_cif | dbadmin | (13 rows) #编辑对象备份脚本,删除不需要 schema ods_ucm [dbadmin@V3 ~]$ vi obj_lizy_20140729.ini [Misc] snapshotName = obj_lizy_20140729 verticaConfig = True restorePointLimit = 3 objects = lizy,ods_ucm [Database] dbName = vertica dbUser = dbadmin dbPassword = 123456 [Transmission] [Mapping] v_vertica_node0001 = 10.75.7.112:/home/dbadmin/backup v_vertica_node0002 = 10.75.7.112:/home/dbadmin/backup v_vertica_node0003 = 10.75.7.112:/home/dbadmin/backup #使用修改后的脚本进行恢复 [dbadmin@V3 ~]$ vbr.py --task restore --config-file obj_lizy_20140729.ini Preparing... Found Database port: 5433 Copying... [==================================================] 100% All child processes terminated successfully. Copying... [================================================================================================== =================================================================================================== ===============[==================================================] 100% All child processes terminated successfully. restore done! #恢复结果显示 schema ods_ucm 自动恢复了 第 50 页 共 182 页 dbadmin=> \dn List of schemas Name | Owner | Comment -------------+---------+--------- v_internal | dbadmin | v_catalog | dbadmin | v_monitor | dbadmin | public | dbadmin | lizy | dbadmin | schema_test | dbadmin | ods_ucm | dbadmin | DEB_CIF | dbadmin | etl_cfg | dbadmin | stg_mic | dbadmin | ods_mic | dbadmin | SYSIBM | dbadmin | dwa_fat | dbadmin | stg_cif | dbadmin | ods_cif | dbadmin | (15 rows) #监控恢复进程的方式 tail -f catalog-path/database-name/node-name_catalog/vertica.log select node_name, recover_epoch, recovery_phase, current_completed, is_running from recovery_status; select node_name, status , progress from projection_recoveries; 4.2.3 Vertica 灾难恢复 灾难恢复的场景主要有以下三个: 1、集群中一个或多个节点失败,但是存活节点能够提供失败节点的数据时,集群能够继续运行,失败节点再次启 动时会从存活节点复制数据进行 recover。 2、集群正常 shutdown 过程中如果有节点出现失败,此时再次启动时会经历场景 1 的过程。 3、集群非正常 shutdown 时节点失败,并且失败节点导致集群无法保证 ksafe 第 51 页 共 182 页 4.2.4 灾难恢复最佳实践 为了避免数据库出现灾难性失败而影响业务的正常运行和造成数据丢失,vertica 建议维护一套离线的 standby,一旦出现灾难时可以快速切换到 standby 系统。而数据丢失的量则跟备份的频率有过。 容灾的设计主要考虑以下两方面的因素: RPO(Recovery point objective):应用能够容忍多少的数据丢失 RTO(Recovery time objective):灾难之后多长时间能够完成恢复 根据不同的 RPO 和 RTO 可以选择以下方案:  Dual-load:每次进行数据导入的过程中,同步导入到另外的一个数据库中。  Periodic Incremental Backups:定期的进行增量备份进行集群拷贝的一个目标数据库。  Replication solutions provided by Storage Vendors:如果是使用 SAN 存储,可以使用 存储厂商的复制技术。 下表对比各种方式的容灾的优缺点: Dual-load Periodic Incremental Backups Replication solutions provided by Storage Vendors RPO 分钟级 上次备份 分钟级 RTO 实时 备份时不可用 实时 优点 Standby 数据库可以单 独配置,而且 standby 可以用来查询 使用内置的脚本 由于数据进行了压缩性能好 数据库上透明 缺点 有可能带来额外 ETL licence 的费用;需要应 用上有错误处理的逻辑 需要完全一致的 standby 系 统 更贵,而且对介质的错误也会同步 4.3 Vertica 集群拷贝 通过一条命令可以实现把集群从一个集群完整复制到另外一个集群,包含原有集群的完整的数据。Vertica 要 求原库和目标库的 data、catalog 目录完全一致。在进行集群拷贝的时候会覆盖目标端的数据库中的数据。 第 52 页 共 182 页 为了完成集群的拷贝,通过系统表 nodes 查看源系统的节点名,在配置目标集群时要求以下配置相同:集群 的节点数量;数据库的名称;节点名称;允许源库的访问;有相同的超级用户,且运行 dbadmin 通过 ssh 无密 码访问;充足的磁盘空间;使用 vbr.py --task copycluster 命令。 运行 copycluster 之前必须先把源库停掉,在执行 copucluster 命令时 vertica 会要求指定 backupHost 选项, 但是会忽略 backupDir,因为备份的目标目录始终是目标节点的 data 和 catalog 目录。 #集群拷贝参数文件 [Misc] snapshotName = CopyVmart verticaConfig = False restorePointLimit = 5 tempDir = /tmp/vbr retryCount = 5 retryDelay = 1 [Database] dbName = vmart dbUser = dbadmin dbPassword = password dbPromptForPassword = False [Transmission] encrypt = False checksum = False port_rsync = 50000 bwlimit = 0 [Mapping] ; backupDir is not used for cluster copy v_vmart_node0001= test-host01:/home/dbadmin/backups v_vmart_node0002= test-host02:/home/dbadmin/backups v_vmart_node0003= test-host03:/home/dbadmin/backups #集群拷贝过程 > vbr.py --config-file CopyVmart.ini --task copycluster Copying... 1871652633 out of 1871652633, 100% All child processes terminated successfully. copycluster done! 第 53 页 共 182 页 5. Projections Vertica 数据库的数据是存放在投影(projection)里,vertica 数据库在对象创建的时候会自动创建一个 supperprojection,supperprojection 主要实现让所有数据查询可见。为了获得最好的性能和压缩比,vertica 建议创建自己的投影。 5.1 创建 Porjection 通过设计(A design is a physical storage plan that optimizes query performance)来创建自己 所需要的投影。 创建设计的流程图: 第 54 页 共 182 页 5.2 创建自定义 Porjection 一般对于表的 projection,需要表上有数据,且数据一般不超过 10GB,太多耗时比较久,太少可能无 法得到最优化的结果。有三种目标:Load、Performance、Balanced,分别对数据加载、存储优化,SQL 语句查询性能优化,折中这两个优化。 通过表 QUERY_REQUESTS 可以查到最近在执行的 SQL 语句信息,如果对表上使用的 SQL 不是特别清楚 的,可以通过该表找出相应的 SQL 并进行 Projection。 有两种方法创建自己的 Projection,一个是使用 admintools 工具进行创建,另外就是使用 SQL 脚本的方式 创建。以下是使用 admintools 创建的方式过程,另外关于使用脚本方式创建 Projection 请参考章节 5.7.3。 #使用 admintools 创建: #运行 admintools 选择 Database Designer $ admintools-> 6 Configuration Menu-> 2 Run Database Designer #选择数据库 #输入 dbadmin 密码 #设定 Database Designer 输出目录 #设置设计的名称 第 55 页 共 182 页 #设置设计的类型 #选择进行设计的模式 #选择部署选项 #选择要提供的 sql 的完整路径 第 56 页 共 182 页 #设定 ksafe 值 #确认是否开始设计 #运行设计和部署的过程 1. Write a script to create the projection, using the CREATE PROJECTION statement. 2. Use the \i meta-command in vsql to run the script. Note: You must have a database loaded with a logical schema. 第 57 页 共 182 页 3. For a K-safe database, use the function SELECT get_projections('table_name') to verify that the projections were properly created. Good projections are noted as being "safe." This means that the projection has enough buddies to be K-safe. 4. If you added the new projection to a database that already has projections that contain data, you need to update the newly created projection to work with the existing projections. By default, the new projection is out-of-date (not available for query processing) until you refresh it. 5. Use the MAKE_AHM_NOW function to set the Ancient History Mark (AHM) to the greatest allowable epoch (now). 6. Use the DROP_PROJECTION function to drop any previous projections that are no longer needed. These projections can waste disk space and reduce load speed if they remain in the database. 7. Run the ANALYZE_STATISTICS function on all projections in the database. This function collects and aggregates data samples and storage information from all nodes on which a projection is stored, and then writes statistics into the catalog. For example: =>SELECT ANALYZE_STATISTICS (''); 5.3 Replicated Projections Replicated Projections :replicated 意为数据跨集群节点的复制 (duplicated on all cluster nodes). 假设 SQL 中最大 row count 和设计表中的最大 row count 相等,那么 DB Designer 建议满足以下条件之 一的情况创建复制的 projection。 •条件 1: largest-row-count < 1,000000 and number of rows in the table <= 10% of largest-row- count. •条件 2: largest-row-count >= 10,000,000 and number of rows in the table <= 1% of largest-row- count. •条件 3: The number of rows in the table <= 100,000. 5.4 分段的 Projections Segmented Projections :segmented 意为数据跨集群节点的分布 (distributed across the cluster nodes),所以数据库不会对单实例数据库进行分段,包括 LONG VARCHAR and LONG VARBINARY 字段的 表也不会创建分段的 Projection。 Segmentation:分段意为把一个 Projection 分成多个小数据块,这些块叫做段,每个段存放在一个集群的 节点。分段可以提高高可用性、恢复性能和查询性能。 第 58 页 共 182 页 Segmentation splits individual projections into chunks of data of similar size, called segments. One segment is created for and stored on each node. Projection segmentation provides high availability and recovery, and optimizes query execution. 创建表和 Projection 的时候可以通过分段子句指定其类型为分段的 Projection,语法如下: SEGMENTED BY expression { ALL NODES [ OFFSET offset ] | NODES node [ ,... ] } 创建表的分段子句指定的是表的 supperprojection 的分段定义,而创建 Projection 的分段子句指定的是所 创建 Projection 的分段定义。 参数 说明 SEGMENTED BY expression 该表达式可以使普通的 SQL 表达式,不过 vertica 建议使用内置的 HASH 或者 MODULARHASH 函数,指定要分段的列作为函数的参数。如果只指定一个列, vertica 会给出一个 Waring。 选择大量唯一值和数据倾斜度在可接受范围的列,主键列一般是比较好的选择。 ALL NODES | NODES node [ ,... ] 在创建 Projection 的过程中自动在每个节点平均的分布数据,节点的排序方式是固 定的。 指定数据分布的节点为集群节点的一个子集,任何 Projection 都只能指定一次节点 范围。 OFFSET offset 可选参数,指定从哪个节点开始做数据分布,忽略 OFFSET 等同于 OFFSET 0, OFFSET 是一个整数值,从 0 开始,最大为所有可用节点,如果指定了 ALL NODES 即为所有节点的节点数。 说明:  创建 Projection 时支持 SITES node 语法格式,为了向之前版本兼容  表达式中的列必须是表的列,而不能是 Projection 的列  灵活的 Projection(当 Projection 创建在启用了 Elastic Cluster 的集群时)分段表达式使用 modularhash 替代 hash。 第 59 页 共 182 页  在分段表达式中不使用 HASH 或者 MODULARHASH 有一些限制条件,表达式必须是常量或者 引用了创建 Projection 时的 SELECT 列表中的列;不能使用聚合函数;表达式返回值不能发生 变化;表达式必须返回非负的整数 0 <= x < 263,在范围内值通常要均匀分布;如果表达式生 成了非期望值(如负值),不会报错,相应的行会放到 Projection 的第一个分段中。 => CREATE PROJECTION ... SEGMENTED BY HASH(C1,C2) ALL NODES; => CREATE PROJECTION ... SEGMENTED BY HASH(C1,C2) ALL NODES OFFSET 1; => CREATE PROJECTION fact_ts_2 ( f_price, f_cid, f_tid, f_cost, f_date) AS ( SELECT price, cid, tid, cost, dwdate FROM fact) SEGMENTED BY MODULARHASH(dwdate) ALL NODES OFFSET 2; 5.5 选择 Encoding 和 Compression 5.5.1 Encoding Vertica 数据库中把数据转换成标准格式的过程叫 Encoding,vertica 可以直接处理编码的数据,而经过压 缩的数据则不能直接处理,vertica 查询处理器会尽可能的使用编码数据以避免解码过程,它同时会把编码数据传 递给其它操作。 合理的列编码格式能够降低数据磁盘存储大小以提升查询的效率,vertica 提供了以下的列编码格式可选:  自动编码 (default):对于 CHAR/VARCHAR, BOOLEAN, BINARY, VARBINARY, and FLOAT 使用 LZO 压缩格式;对于 INTEGER, DATE/TIME, TIMESTAMP, and INTERVAL 使用基于连续列值的 delta 的算法进行压缩。它适合排序列,多值列(如主键), CPU 消耗低,在最坏的情况下,数据可能会扩大百分之八(8%)对 LZO 和百分之二十(20%) 对于整数数据。  BLOCK_DICT 编码:对于每个存储块,vertica 会计算每一个列的唯一值并把它写入到一个数 据字典中,然后存储一个数据字典和数据块的索引。BLOCK_DICT 适合处理列值较少且没有排 序的情况,这种情况下节省空间比编码效率更重要,Long CHAR ,VARCHAR 不适合使用 BLOCK_DICT 编码,这种编码方式 CPU 消耗会增多。  BLOCKDICT_COMP 编码:它和 BLOCK_DICT 类似,不过存储时熵编码的方式存储索引。如 果列的值严重倾斜,这种编码能有效节省空间。  COMMONDELTA_COMP 编码:这种压缩方式对所有 delta 数据在数据块中创建一个数据字 典,然后存储索引到 delta 数据字典中,并使用熵编码格式。它比较适合处理排序的 FLOAT, 第 60 页 共 182 页 INTEGER-based (DATE/TIME/TIMESTAMP/INTERVAL)数据列,并且以一种可以预计的序列存 储,如:周期内递增的时间戳。如果 delta 数据分别良好,它能够实现每行不到一位的列存储长 度,但是需要消耗较多 CPU,另外如果 delta 数据是随机的,它可能会造成大量的空间浪费。  DELTARANGE_COMP 编码:主要是用来存储 float-point 数据,每一个数据都存储为前一个 数据的 delta。它适合处理多值的浮点列,比如进行了排序或者定义了范围。不要使用在包含 null 的未排序列,这种方式压缩和解压代价都很高。  DELTAVAL 编码:对于 INTEGER , DATE/TIME/TIMESTAMP/INTERVAL 列,数据块 记录了列值和最小值的差别。它适合处理多值未排序的数字型数据,CPU 消耗低,对其它数据无 效。  GCDDELTA 编码:对于 INTEGER , DATE/TIME/TIMESTAMP/INTERVAL 列以及长 度小于 18 的 NUMERIC 列,数据块记录了列值和最小值的差别除以所有数据块的 greatest common divisor (GCD)。它适合处理多值未排序的数字型数据,且数据都有一个共同的操作符, 它 CPU 消耗低,对其它数据无效。  RLE 编码:它使用唯一值和值重复读记录数据,它最适合处理低键值的列且出现在 Projection 的 order by 子句中,且最好平均重复度大于 10,存储上它和 AUTO 编码中的 CHAR, VARCHAR, BINARY, VARBINARY 一样。  NONE 编码:它是一种向上兼容的格式,除了 CHAR and VARCHAR 以外,其它情况和 auto 编 码相同。 5.5.2 Compression 把数据改变成压缩的格式的过程叫 Compression,压缩的数据无法直接处理,必须经过解压缩过程。 Vertica 使用数字打包未编码的数字格式数据和 LZO 压缩可压缩的数据。尽管压缩被认为是编码的一种表现形式, vertica 数据库中它们有不同的含义。 5.6 选择列的 Sort Order Vertica 数据库中 Projection 里面的列的排序顺序往往决定了,表的压缩率、SQL 的性能等,一般如果谓词 是在基数低列上,那么使用 RLE 和 Sort 能有效的提升查询性能和提高压缩比。基数越高压缩比越低,列的长度 越长压缩比越高。为了能够最大限度的提升 RLE 的效率,应只在列的平均 run length 大于 10 且排序的时候使 用 RLE。另外还有以下需要注意的优化项: 1、 对于有相关性的列,把基数低的列放前面。 2、 合理的选择 sort merge join 或者 hash join,当对象已经排序时 sort merge join 由于不需要预处理, 性能优,而如果对象无序且小表可以完全放入内存做 hash table 时 hash join 性能更优。 3、 对于重要的 SQL 语句,如果列基数比较高,需要牺牲部分存储换取 SQL 性能的优化。 4、 如果有两列基数相同,那么把列长度长的放在前面,压缩比会更高。 第 61 页 共 182 页 5.7 程序中进行 Projection 设计 当获得 DBUSER 角色并启用之后,就可以进行 DB Designer 的相关设计。使用 DESIGNER_*相关的命令 行函数可以进行下列设计:  创建全量和增量的设计  设计中增加表和查询  设置优化的目标是查询性能还是存储大小  给查询分配权重  给设计分配 ksafe 值  分析设计中表的统计信息  生成创建 Projection 的 DDL 脚本  部署设计  指定 Projection 的分段方式  发布一个设计  取消正在运行的设计  等待正在运行设计的完成  自动部署设计  删除已完成或中断的设计的对象 5.7.1 何时进行设计 以下列出了一些在程序中进行 Projection 设计的场景:  优化表相关的性能  创建和更新设计而不必超级用户或 DBA 介入  添加单独的表和查询或者数据,运行 Database Designer 基于最新信息进行设计  自定义设计  使用最近执行的查询来设置你的数据库,以定期自动运行 Database Designer。  给设计中的查询分配权重 第 62 页 共 182 页 5.7.2 设计相关函数 以下是设计相关的函数的简单说明,如需了解每一个函数的详细使用请参考官方文档中这些函数的说明。 函数类别 函数名 函数作用 设置函数 DESIGNER_CREATE_DESIGN 创建指定名字的设计 配置函数 DESIGNER_DESIGN_PROJECTION_ENCODINGS 检查指定列表的 Projection 的编码方式,生成建议 编码脚本,部署所建议编码 DESIGNER_SET_DESIGN_KSAFETY 设置全量设计的 ksafe 值 DESIGNER_SET_OPTIMIZATION_OBJECTIVE 分配设计的优化目标:QUERY、LOAD、BALANCED DESIGNER_SET_DESIGN_TYPE 指定设计的类型:COMPREHENSIVE、 INCREMENTAL DESIGNER_SET_PROPOSED_UNSEGMENTED_PROJECTIONS 指定设计的 Projection 是否分段,默认是分段的 DESIGNER_SET_ANALYZE_CORRELATIONS_MODE 指定如何在设计中处理列之间的相互关系,有四种 级别:0,忽略列之间的相互关系,默认的级别; 1,考虑现存的相互关系,如果未发现相互关系则 忽略;2,分析之前未进行列相互关系分析的列的 相互关系;3,分析列的相互关系即便是之前已经 进行过列相互关系分析 输入函数 DESIGNER_ADD_DESIGN_QUERIES 读取和解析指定文件中的所有查询,把已接受的查 询添加到设计中并设置权重为 1 DESIGNER_ADD_DESIGN_QUERIES_FROM_RESULTS 解析并执行用户查询,把包含 QUERY_TEXT 和 QUERY_WEIGHT 的查询返回,如果 QUERY_WEIGHT 为空则设置为默认值 1 DESIGNER_ADD_DESIGN_QUERY 读取并解析指定的查询语句,如果可以接受则添加 到设计中 DESIGNER_ADD_DESIGN_TABLES 增加指定的表到设计中 部署函数 DESIGNER_RUN_POPULATE_DESIGN_AND_DEPLOY 生成创建 Projection 和部署的脚本,发布设计,如 果进行了指定它同时可以分析统计信息、部署设 计、部署之后删除工作区 DESIGNER_WAIT_FOR_DESIGN 等待当前运行的设计的结束 输出函数 DESIGNER_OUTPUT_ALL_DESIGN_PROJECTIONS 在标准输出上显示设计中所有的 DDL 语句 DESIGNER_OUTPUT_DEPLOYMENT_SCRIPT 在表示输出上显示部署脚本 清理函数 DESIGNER_CANCEL_POPULATE_DESIGN 取消当前运行设计的发布或部署 第 63 页 共 182 页 DESIGNER_DROP_DESIGN 删除指定设计的所有内容,在设计部署或中断之后 用其清理设计相关内容 DESIGNER_DROP_ALL_DESIGNS 删除和当前用户相关的所有的设计 => SELECT DESIGNER_SET_DESIGN_TYPE( 'VMART_DESIGN', 'COMPREHENSIVE'); DESIGNER_SET_DESIGN_TYPE -------------------------- 0 (1 row) => SELECT DESIGNER_SET_DESIGN_TYPE( 'VMART_DESIGN', 'INCREMENTAL'); DESIGNER_SET_DESIGN_TYPE -------------------------- 0 (1 row) => SELECT DESIGNER_SET_PROPOSE_UNSEGMENTED_PROJECTIONS( 'VMART_DESIGN', 'false'); => SELECT DESIGNER_SET_ANALYZE_CORRELATIONS_MODE ( 'VMART_DESIGN', '3); DESIGNER_SET_ANALYZE_CORRELATIONS_MODE ---------------------------------------- 3 (1 row) => SELECT DESIGNER_ADD_DESIGN_QUERIES ( 'VMART_DESIGN', '/tmp/examples/vmart_queries.sql', 'true' ); ... DESIGNER_ADD_DESIGN_QUERIES ---------------------------------------------------- Number of accepted queries =9 Number of queries referencing non-design tables =0 Number of unsupported queries =0 第 64 页 共 182 页 Number of illegal queries =0 (1 row) => SELECT DESIGNER_ADD_DESIGN_QUERIES_FROM_RESULTS ( 'VMART_DESIGN', 'SELECT request AS query_text FROM query_requests ORDER BY start_timestamp DESC LIMIT 10;' ); => SELECT DESIGNER_ADD_DESIGN_QUERY ( 'VMART_DESIGN', 'SELECT customer_name, customer_type FROM vmart_design ORDER BY customer_name ASC;', 0.5 ); => SELECT DESIGNER_ADD_DESIGN_TABLES( 'VMART_DESIGN', 'online_sales.*', 'true' ); DESIGNER_ADD_DESIGN_TABLES ---------------------------- 9 (1 row) => SELECT DESIGNER_ADD_DESIGN_TABLES( 'VMART_DESIGN', 'public.*', 'true' ); DESIGNER_ADD_DESIGN_TABLES ---------------------------- 9 (1 row) => SELECT DESIGNER_ADD_DESIGN_TABLES( 'VMART_DESIGN', 'store.*', 'true' ); DESIGNER_ADD_DESIGN_TABLES ---------------------------- 3 第 65 页 共 182 页 (1 row) => SELECT DESIGNER_OUTPUT_ALL_DESIGN_PROJECTIONS('vmart_design'); CREATE PROJECTION customer_dimension_DBD_1_rep_VMART_DESIGN /*createtype(D)*/ ( customer_key ENCODING DELTAVAL, customer_type ENCODING AUTO, customer_name ENCODING AUTO, customer_gender ENCODING REL, title ENCODING AUTO, household_id ENCODING DELTAVAL, customer_address ENCODING AUTO, customer_city ENCODING AUTO, customer_state ENCODING AUTO, customer_region ENCODING AUTO, marital_status ENCODING AUTO, customer_age ENCODING DELTAVAL, number_of_children ENCODING BLOCKDICT_COMP, annual_income ENCODING DELTARANGE_COMP, occupation ENCODING AUTO, largest_bill_amount ENCODING DELTAVAL, store_membership_card ENCODING BLOCKDICT_COMP, customer_since ENCODING DELTAVAL, deal_stage ENCODING AUTO, deal_size ENCODING DELTARANGE_COMP, last_deal_update ENCODING DELTARANGE_COMP ) AS SELECT customer_key, customer_type, customer_name, customer_gender, title, household_id, customer_address, customer_city, customer_state, customer_region, marital_status, customer_age, number_of_children, annual_income, occupation, 第 66 页 共 182 页 largest_bill_amount, store_membership_card, customer_since, deal_stage, deal_size, last_deal_update FROM public.customer_dimension ORDER BY customer_gender, annual_income UNSEGMENTED ALL NODES; CREATE PROJECTION product_dimension_DBD_2_rep_VMART_DESIGN /*+createtype(D)*/ ( ... => SELECT DESIGNER_OUTPUT_DEPLOYMENT_SCRIPT('VMART_DESIGN'); CREATE PROJECTION customer_dimension_DBD_1_rep_VMART_DESIGN /*createtype(D)*/ ... CREATE PROJECTION product_dimension_DBD_2_rep_VMART_DESIGN /*+createtype(D)*/ ...select refresh('public.customer_dimension, public.product_dimension, public.promotion.dimension, public.date_dimension'); select make_ahm_now(); DROP PROJECTION public.customer_dimension_super CASCADE; DROP PROJECTION public.product_dimension_super CASCADE; ... => SELECT DESIGNER_DROP_ALL_DESIGNS(); DESIGNER_DROP_ALL_DESIGNS --------------------------- 2 (1 row) 5.7.3 设计案例 以下是通过一个案例详细说明在程序中进行 Projection 设计的过程。Vertica 建议在进行设计之前通过 EXPORT_CATALOG 备份当前已有的设计。  1、创建表 dbadmin=> CREATE TABLE T( dbadmin(> x INT, dbadmin(> y INT, dbadmin(> z INT, dbadmin(> u INT, 第 67 页 共 182 页 dbadmin(> v INT, dbadmin(> w INT PRIMARY KEY dbadmin(> ); CREATE TABLE  2、导入数据 dbadmin=> \! perl -e 'for ($i=0; $i<100000; ++$i) {printf("%d, %d, %d, %d, %d, %d\n", $i/10000, $i/100, $i/10, $i/2, $i, $i);}' | vsql -c "COPY T FROM STDIN DELIMITER ',' DIRECT;" Password: dbadmin=> select count(*) from t; count -------- 100000 (1 row)  3、创建第二张表 dbadmin=> CREATE TABLE T2( dbadmin(> x INT, dbadmin(> y INT, dbadmin(> z INT, dbadmin(> u INT, dbadmin(> v INT, dbadmin(> w INT PRIMARY KEY dbadmin(> ); CREATE TABLE  4、复制数据 dbadmin=> INSERT /*+DIRECT*/ INTO T2 SELECT * FROM T; OUTPUT -------- 100000 (1 row) dbadmin=> commit; COMMIT  5、创建设计 dbadmin=> SELECT DESIGNER_CREATE_DESIGN('my_design'); DESIGNER_CREATE_DESIGN ------------------------ 0 (1 row)  6、往设计中增加表 dbadmin=> SELECT DESIGNER_ADD_DESIGN_TABLES('my_design', 'public.t'); 第 68 页 共 182 页 DESIGNER_ADD_DESIGN_TABLES ---------------------------- 1 (1 row) dbadmin=> SELECT DESIGNER_ADD_DESIGN_TABLES('my_design', 'public.t2'); DESIGNER_ADD_DESIGN_TABLES ---------------------------- 1 (1 row)  7、往设计中增加 SQL dbadmin=> \! cat /tmp/examples/queries.txt SELECT DISTINCT T2.u FROM T JOIN T2 ON T.z=T2.z-1 WHERE T2.u > 0; SELECT DISTINCT w FROM T; dbadmin=> SELECT DESIGNER_ADD_DESIGN_QUERIES dbadmin-> ('my_design', dbadmin(> '/tmp/examples/queries.txt', dbadmin(> 'true' dbadmin(> ); DESIGNER_ADD_DESIGN_QUERIES --------------------------------------------------- Number of accepted queries =2 Number of queries referencing non-design tables =0 Number of unsupported queries =0 Number of illegal queries =0 (1 row)  8、进行全量设计,替换已有的 Projection dbadmin=> SELECT DESIGNER_SET_DESIGN_TYPE('my_design', 'comprehensive'); DESIGNER_SET_DESIGN_TYPE -------------------------- 0 (1 row)  9、设定设计的目标是查询 dbadmin=> SELECT DESIGNER_SET_OPTIMIZATION_OBJECTIVE('my_design', 'query'); DESIGNER_SET_OPTIMIZATION_OBJECTIVE ------------------------------------- 0 (1 row)  10、生成设计脚本,收集统计信息、不部署设计、部署设计之后不进行删除、遇到错误停止 dbadmin=> SELECT DESIGNER_RUN_POPULATE_DESIGN_AND_DEPLOY 第 69 页 共 182 页 dbadmin-> ('my_design', dbadmin(> '/tmp/examples/my_design_projections.sql', dbadmin(> '/tmp/examples/my_design_deploy.sql', dbadmin(> 'True', dbadmin(> 'False', dbadmin(> 'False', dbadmin(> 'False' dbadmin(> ); DESIGNER_RUN_POPULATE_DESIGN_AND_DEPLOY ----------------------------------------- 0 (1 row)  11、检查所生成的推荐的 Projection 的状态 dbadmin=> SELECT * FROM OUTPUT_DEPLOYMENT_STATUS; deployment_id | design_name | deployment_projection_id | deployment_projection_name | deployment_status | error_message -------------------+-------------+--------------------------+----------------------------+-------------------+--------------- 49539595901541730 | my_design | 1 | T_DBD_1_seg_my_design_b0 | pending | N/A 49539595901541730 | my_design | 2 | T2_DBD_2_seg_my_design_b0 | pending | N/A 49539595901541730 | my_design | 3 | T_DBD_1_seg_my_design_b1 | pending | N/A 49539595901541730 | my_design | 4 | T2_DBD_2_seg_my_design_b1 | pending | N/A 49539595901541730 | my_design | 5 | T_b1 | pending | N/A 49539595901541730 | my_design | 6 | T_b0 | pending | N/A 49539595901541730 | my_design | 7 | T2_b1 | pending | N/A 49539595901541730 | my_design | 8 | T2_b0 | pending | N/A (8 rows)  12、检查脚本/tmp/examples/my_design_deploy.sql 了解 Projection 详细信息 dbadmin=> \! cat /tmp/examples/my_design_deploy.sql CREATE PROJECTION T_DBD_1_seg_my_design_b0 /*+basename(T_DBD_1_seg_my_design),createtype(D)*/ ( x ENCODING COMMONDELTA_COMP, y ENCODING COMMONDELTA_COMP, z ENCODING COMMONDELTA_COMP, u ENCODING COMMONDELTA_COMP, v ENCODING COMMONDELTA_COMP, w ENCODING COMMONDELTA_COMP ) AS SELECT x, y, z, u, v, 第 70 页 共 182 页 w FROM public.T ORDER BY w SEGMENTED BY MODULARHASH (w) ALL NODES OFFSET 0; CREATE PROJECTION T_DBD_1_seg_my_design_b1 /*+basename(T_DBD_1_seg_my_design),createtype(D)*/ ( x ENCODING COMMONDELTA_COMP, y ENCODING COMMONDELTA_COMP, z ENCODING COMMONDELTA_COMP, u ENCODING COMMONDELTA_COMP, v ENCODING COMMONDELTA_COMP, w ENCODING COMMONDELTA_COMP ) AS SELECT x, y, z, u, v, w FROM public.T ORDER BY w SEGMENTED BY MODULARHASH (w) ALL NODES OFFSET 1; CREATE PROJECTION T2_DBD_2_seg_my_design_b0 /*+basename(T2_DBD_2_seg_my_design),createtype(D)*/ ( x ENCODING COMMONDELTA_COMP, y ENCODING COMMONDELTA_COMP, z ENCODING COMMONDELTA_COMP, u ENCODING COMMONDELTA_COMP, v ENCODING COMMONDELTA_COMP, w ENCODING COMMONDELTA_COMP ) AS SELECT x, y, z, u, v, w FROM public.T2 ORDER BY u SEGMENTED BY MODULARHASH (u) ALL NODES OFFSET 0; 第 71 页 共 182 页 CREATE PROJECTION T2_DBD_2_seg_my_design_b1 /*+basename(T2_DBD_2_seg_my_design),createtype(D)*/ ( x ENCODING COMMONDELTA_COMP, y ENCODING COMMONDELTA_COMP, z ENCODING COMMONDELTA_COMP, u ENCODING COMMONDELTA_COMP, v ENCODING COMMONDELTA_COMP, w ENCODING COMMONDELTA_COMP ) AS SELECT x, y, z, u, v, w FROM public.T2 ORDER BY u SEGMENTED BY MODULARHASH (u) ALL NODES OFFSET 1; select refresh('public.T, public.T2'); select make_ahm_now(); DROP PROJECTION public.T_b0, public.T_b1 CASCADE;  13、执行部署脚本 \i /tmp/examples/my_design_deploy.sql  14、最后删除设计 SELECT DESIGNER_DROP_DESIGN('my_design'); 6. 负载均衡 6.1 自带的负载均衡- Native Connection Load Balancing 自带的负载均衡是通过 vertica 服务器端和客户端的库文件实现的应用层负载均衡,相比 IPVS 自带的负载均 衡有以下优势: 第 72 页 共 182 页 1)容易设置,自带负载均衡只需要设置参数和启用负载均衡即可,IPVS 则需要安装额外的软件和进行一些 网络的配置。 2)必要时容易覆盖,比如使用 copy 加载数据时指定 host。 3)自带的负载均衡单点故障风险较低,IPVS 则依赖网关节点及其备份,容易出现单点故障。 4)CPU 和内存消耗更低 5)IPVS 由于所有连接都需要经过集群的网关才能跳转到连接实例,所以增加了网络的延迟。 6)HP 对自带的负载均衡提供厂商支持,IPVS 则没有支持 7)自带负载均衡在所有操作系统平台都支持,HP 只认准了 redhat 平台 IPVS。 6.1.1 启用了自带负载均衡之后的连接过程: 1)客户端通过带负载均衡参数的连接到集群的某一个节点,请求一个负载均衡的连接。 2)该节点负责根据指定的负载均衡策略选择一个当前存活的节点。 3)该节点告诉客户端哪个节点并选择了处理连接请求。 4)如果该节点选择了其它的节点来处理连接请求,那么客户端要端口同该节点的连接,否则跳转到步骤 6。 5)客户端建立同选定节点的连接,同时客户端设置该连接为第二次连接以避免选择节点认为该连接为需要处 理的负载均衡连接。 6)客户端继续进行后续处理,如权限认证等过程。 需要说明的是,A、自带负载均衡如果使用 ADO.NET 驱动的连接池,则初始连接和负载均衡连接都可以是 连接池的连接;B、如果客户端使用 ODBC、JDBC 驱动连接的第三方连接池,则初始连接不是连接池连接, 因为它不是一个完整的客户端请求,负载均衡连接则是连接池的连接;C、客户端的库文件中还包括了 FAILOVER 的机制,当连接配置的节点无法访问时,可以通过该机制访问其备份节点,但是负载均衡的连接 节点无法访问时不会 failover,客户端会收到连接报错。 6.1.2 负载均衡策略和实现 通过 SET_LOAD_BALANCE_POLICY 可以设置负载均衡的连接策略,有以下策略可选: 1)NONE,不使用自带负载均衡,这是默认的策略。 2)ROUNDROBIN,从当前存活的节点列表中选择下一个连接的节点,每个节点负责维护自己的连接编号。 3)RANDOM,随机的从当前存活节点列表选择一个节点。 为了现实负载均衡,除了服务器端设置相应的策略外,客户端还需要指定 ConnectionLoadBalance=true 第 73 页 共 182 页 可以通过 SELECT LOAD_BALANCE_POLICY FROM V_CATALOG.DATABASES 查询当前的 loadbalance 策略。 需要说明的是,如果使用了私网 IP 和公网分开的方式创建集群,则需要参考 2.1 章节的步骤设置集群的 export IP 和网卡,否则无法实现自动的负载均衡 6.2 IPVS 负载均衡- Internet Protocol Virtual Server IPVS 是 Linux 内核级别的通过让集群中一个 host 做网关来实现集群的负载均衡的一种网络层面的负载均衡 机制。由于自带负载均衡的一些优势,一般情况下应优先选择自带负载均衡,除非网络上对 vertica 服务器和应 用服务器之间有防火墙现在,无法直接连接到 vertica 服务器时考虑使用 IPVS。 IPVS 的组件和架构图如下所示: 7. 数据加载 Vertica 的数据加载可以使用批量加载工具 copy 进行,vertica 的 copy 命令集成了 oracle 的 sqlldr 和 copy 命令的功能。Vertica 自身的混合存储模型能够非常灵活的支持数据加载和管理。 7.1 Tuple Mover 原理 下图是 vertica 的混合存储模型架构图: 第 74 页 共 182 页 需要说明的是,Write Optimized Store (WOS)是驻留内存的数据结构,用来存储 INSERT, UPDATE, DELETE, and COPY (without DIRECT hint)的数据,和 Read Optimized Store (ROS)类似,WOS 也是根据 Projection 的使用而使用的,为了支持快速的数据插入和查询,WOS 中的 Projection 只在被查询的时候存在, 且存储的数据不进行压缩和索引,并一直保持排序状态。另外 WOS 的数据按 epoch 来组织,并保持提交的和未 提交的数据。 Tuple Mover (TM)是 vertica 一个优化组件用来把 WOS 的数据移动到 ROS 中,它同时会把以下小的 ROS 合并为大的 ROS,以及清空已删除的数据。在 TM 的 moveout 移出过程中,它按照一定的间隔自动的进行存储 位置和存储策略的关联。 ROS 是经过高度优化的、读取导向的、按 Projection 组织的磁盘存储结构,ROS 进行大量的压缩和索引, 可以通过 COPY...DIRECT and INSERT (with /*+direct*/ hint)直接写入 ROS 中。 7.1.1 TM moveout TM 会进行两种操作,分别是 moveout 和 mergeout,其中 moveout 操作会把数据从 WOS 写入到 ROS 中, 一般可以有操作 moveout、copy direct 触发,过程类似如下: 第 75 页 共 182 页 7.1.2 TM mergeout Mergeout 是 ROS 容器的顾问进程发起的,能够进行删除数据的清理、碎片的整理等。Vertica 默认会把不 同的分区数据放在不同的磁盘,mergeout 操作不会把分区数据合并,一个新的分区是需要加载数据和 TM 进程 关注的分区,随着分区的老化关注度会降低,TM 有两种策略管理不同分区的负载: 1、活跃分区,经常进行加载和修改,TM 使用 STRATA mergeout 策略以保障一系列的 ROS 容器大小已达 到最小化 mergeout 操作的次数,(Contains internal details of how the Tuple Mover combines ROS containers in each projection, broken down by stratum and classifies the ROS containers by size and partition)。 2、分活跃分区,TM 合并 ROS 容器到一个最小集合,以避免合并大小超过 MaxMrgOutROSSizeMB 值的 容器。 分区的活跃度不是有指定的,TM 通过下面算法进行判断 1、分区创建越早就越不活跃 2、创建时间相同的分区,最后更新时间越早就越不活跃 3、创建时间和最后更新时间相同的,分区键值小的不活跃 可以手动使用函数 DO_TM_TASK 进行 mergeout 操作,此时所有分区会被合并到尽可能少的容器中,同时 忽略操作 ActivePartitionCount 限制。 Vertica 删除数据的时候不会直接把数据彻底删掉,而是加一个删除标志,使用 delete 进行频繁的删除时会 生成大量的存放删除标志的容器,它们需要消耗资源同时影响性能,尤其需要恢复的时候。Mergeout 操作会把 这些容器合并成一个大的容器,但是它并不把 deleted 数据清空。 系统表 V_MONITOR.DELETE_VECTORS 可以看到删除的数据和容器。 7.1.3 TM 性能优化 TM 默认的配置足以应对大多数情况下的负载了,可以通过以下过程进行相关的优化 第 76 页 共 182 页 TM 相关的参数: 参数 描述 ActivePartitionCount 设置活跃分区的个数,默认为 1,可以通过以下 sql 修改 SELECT SET_CONFIG_PARAMETER ('ActivePartitionCount', 2); MergeOutInterval TM 进行 mergeout 的时间间隔,如果 ROS 容器加载频繁需要考虑降低该值,默认 是 600s,可以通过以下 sql 修改 SELECT SET_CONFIG_PARAMETER ('MergeOutInterval', 1200); MoveOutInterval TM 进行 moveout 的时间间隔,默认是 300s,可以通过以下 sql 修改 SELECT SET_CONFIG_PARAMETER ('MoveOutInterval', 600); MoveOutMaxAgeTime TM 强制把 WOS 写入到磁盘的时间间隔,默认 1800s,可以通过以下 sql 修改 SELECT SET_CONFIG_PARAMETER ('MoveOutMaxAgeTime', 1200); MoveOutSizePct TM 进行 moveout 前 WOS 可以写入数据的百分比,默认是 0, SELECT SET_CONFIG_PARAMETER ('MoveOutSizePct', 50); TM 的资源调度通过 TM 资源池进行,增加内存提高并发度可以使 TM 更高效的处理高负载,并发度是有参 数 PLANNEDCONCURRENCY 控制,它决定进行 merge 操作的线程数,需要注意的是它必须要和 RAM、CPU、 Storage 相匹配,如提高该参数可能会导致 Storage 出现 IO 瓶颈,如果发现长 IO 队列,写延迟增加说明存储出 现瓶颈,考虑降低该参数。 #设置内存并发度的 sql: ALTER RESOURCE POOL tm MEMORYSIZE '4G' PLANNEDCONCURRENCY 4 MAXCONCURRENCY 5; WOSDATA 资源池间接的影响 TM 的性能,自动模式下 INSERT 、 COPY 根据并行的设置决定数据是否够 小能够放入 WOS 或者太大必须放入 ROS 中,它还决定 WOS 可用的 RAM 大小,把它设置为所希望并发 load 的数量。 #设置 wosdata 资源池的参数 ALTER RESOURCE POOL wosdata MAXMEMORYSIZE '4G' PLANNEDCONCURRENCY 3; Load 数据过程中 vertica 自动决定数据存储 WOS 或者 ROS,对于小数据加载,通过先加载到 WOS,再由 自动的 TM 设置完成后续工作时最好的办法。对于大量加载时,通过 MergeOutInterval、MoveOutInterval 调 整 TM 调度的频率。 Reduce the MoveOutInterval if you expect the peak load rate to fill the WOS quickly. Reduce MergeOutInterval if you anticipate performing many DIRECT loads or inserts. 系统资源使用率可以通过以下 sql 查询 第 77 页 共 182 页 dbadmin=>select * from SYSTEM_RESOURCE_USAGE where end_time>sysdate-1/24 order by node_name asc,end_time desc limit 3; -[ RECORD 1 ]----------------+-------------------- node_name | v_vertica_node0001 end_time | 2014-08-08 16:58:00 average_memory_usage_percent | 45.26 average_cpu_usage_percent | 3.2 net_rx_kbytes_per_second | 15.54 net_tx_kbytes_per_second | 15.65 io_read_kbytes_per_second | 0 io_written_kbytes_per_second | 209.71 -[ RECORD 2 ]----------------+-------------------- node_name | v_vertica_node0001 end_time | 2014-08-08 16:57:00 average_memory_usage_percent | 45.2 average_cpu_usage_percent | 1.82 net_rx_kbytes_per_second | 0.8 net_tx_kbytes_per_second | 0.57 io_read_kbytes_per_second | 0.13 io_written_kbytes_per_second | 231.47 -[ RECORD 3 ]----------------+-------------------- node_name | v_vertica_node0001 end_time | 2014-08-08 16:56:00 average_memory_usage_percent | 45.22 average_cpu_usage_percent | 3.28 net_rx_kbytes_per_second | 15.67 net_tx_kbytes_per_second | 16.22 io_read_kbytes_per_second | 0.53 io_written_kbytes_per_second | 247.35 7.2 从文本文件 Copy 加载 Vertica 希望导入数据的格式为 Unicode UTF-8,其它字符如 ISO 8859-1 (Latin1)为非 UTF-8 兼容格式, 需要导入前进行转换 [dbadmin@V1 u01]$ file cell_31 cell_31: ASCII text, with CRLF line terminators [dbadmin@V1 u01]$ wc cell_31 540388149 2868804394 36494006490 cell_31 iconv -f ISO88599 -t utf-8 data2.txt > data2-utf8.txt SELECT name FROM nametable WHERE ISUTF8(name) = FALSE; 第 78 页 共 182 页 select * from LOAD_STREAMS where session_id in (select session_id from sessions); 8. Vertica 监控 8.1 系统日志 数据库运行时会记录信息到 catalog-path/database-name/node-name_catalog/vertica.log 文件,而在 数据库启动的过程中会记录信息到 catalog-path/database-name/dbLog Vertica 使用 linux 系统自动的工具 logrotate 进行日志文件的管理,如果在安装 vertica 软件之前,系统已 正确安装了 logrotate 工具,则 vertica 会自动进行 logrotate 的配置;如果安装 vertica 时系统未安装 logrotate, 则要么重装 vertica 软件要么手动配置 logrotate,配置时需要手动做如下操作:  创建配置文件/etc/logrotate.d/vertica,包含 include /opt/vertica/config/logrotate  对于机器的数据库,需要创建配置文件/opt/vertica/config/logrotate/ #以下是配置文件/opt/vertica/config/logrotate/示例 [dbadmin@V1 logrotate]$ pwd /opt/vertica/config/logrotate [dbadmin@V1 logrotate]$ cat vertica /home/dbadmin/catalog/vertica/v_vertica_node0001_catalog/vertica.log /home/dbadmin/catalog/vertica/v_vertica_node0001_catalog/UDxLogs/UDxFencedProcesses.log { # rotate weekly weekly # and keep for 52 weeks rotate 52 # no complaining if vertica did not start yet missingok # compress log after rotation compress # no creating a new empty log, vertica will do that nocreate # if set, only rotates when log size is greater than X size 10M # delete files after 90 days (not all logrotate pkgs support this keyword) # maxage 90 # we have 2 log files to rotate but only signal vertica once sharedscripts # signal vertica to reopen and create the log postrotate kill -USR1 `head -1 /home/dbadmin/catalog/vertica/v_vertica_node0001_catalog/vertica.pid 2> /dev/null` 2> /dev/null || true endscript } /home/dbadmin/catalog/vertica/dbLog { 第 79 页 共 182 页 # rotate weekly weekly # and keep for 52 weeks rotate 52 # no complaining if vertica did not start yet missingok # compress log after rotation compress # this log is stdout, so rotate by copying it aside and truncating copytruncate } [dbadmin@V1 logrotate]$ cat /etc/logrotate.d/vertica include /opt/vertica/config/logrotate admintools 提供了对集群数据库的 logrotate 部分功能配置: #如下所示,修改日志保存 12 周 admintools -t logrotate -d -r weekly -k 12 除此之外也可以进行手动的日志 rotate,参考步骤如下: #1.修改日志文件名: $ mv vertica.log vertica.log.1 #2.发送 Vertica 进程 USR1 信号: $ killall -USR1 vertica or $ ps -ef | grep -i vertica $ kill -USR1 process-id 8.2 事件监控 Vertica 的事件监控机制通过以下方式实现:  vertica.log:所有事件都自动记录在 vertica.log 中。  ACTIVE_EVENTS:该系统表提供了所有 open 状态的事件。  SNMP:捕获事件并发送给 SNMP,提供全局的事件报告。  Syslog:记录每一个单独的事件到 Syslog 中。 Vertica 记录并追踪以下的事件,以下事件名区分空格和大小写: 事件名 类型 描述 解决方案 第 80 页 共 182 页 Low Disk Space 0 磁盘空间不足、磁盘损坏或 磁盘 IO 异常 尽快增加磁盘空间或者替换损坏磁盘或硬件;使用操作系统命令 dmesg 检查造成问题的原因;检查 DISK_RESOURCE_REJECTIONS 系统表找出被拒绝的请求信息 Read Only File System 1 数据库没有写 data 或者 catalog 的权限 修改文件系统属性,增加数据库的写权限 Loss Of K Safety 2 数据库无法保证 ksafety 数据库会由于无法保证 ksafe 而宕库,此时重新启动数据库需要进行 recover Current Fault Tolerance at Critical Level 3 如果集群再宕一个节点集群 就不能保证 ksafe 的状态 恢复已关闭的或者异常损坏的节点 Too Many ROS Containers 4 由于太多的数据加载操作导 致 ROS 小容器太多,一般情 况下 TM mergeout 滞后是产 生这种情况的原因。太多 ROS 小容器会耗尽系统资 源,为了避免这种情况的发 生,系统自动回滚部分加载 数据的操作指导 TM mergeout 能够追上 可以通过配置 TM 的 mergeout 频率产生来适应数据加载的节奏。 查询系统表 TUPLE_MOVER_OPERATIONS 可以监控 TM mergeout 活动的状态,TM 并不会在 Projection 达到限制进而收到 这个事件后立即进行 mergeout 操作。 如果等待 mergeout 并不能解决这个问题的话,很可能是由于内存不 够。一个比较简单的计算规则去检查系统内存是否够用,系统 RAM(以 MB 为单元)除以 6 倍的表最大列数量大于 10。 WOS Over Flow 5 WOS 无法保存过多试图加载 的数据,意味着加载会失 败,该报错发生在 4.0 以前 版本 考虑把数据直接加载到 ROS 而不是 WOS,或者把加载的文件切分 成多段,然后逐段加载。 另外也可以考虑缩短 TM moveout 的频率。 Node State Change 6 节点状态变化 检查节点的状态 admintools -t view_cluster Recovery Failure 7 数据库在出现硬件或者软件 失败之后没有从一个功能状 态恢复 检查恢复失败的原因 Recovery Error 8 数据库恢复时遇到错误,当 恢复错误超过最大尝试值时 报出该错误 检查恢复失败的原因 Recovery Lock Error 9 一个正在恢复的节点无法获 取表的 S 型锁,比如连续的 COPY 执行时,恢复可能一 直无法完成 要么暂停数据加载要么暂停节点的 recover 等待系统空闲时再继续 Recovery Projection Retrieval Error 10 数据库无法获取 Projection 的信息 有很多可能原因,需要根据事件的具体描述具体问题具体分析 Refresh Error 11 数据库刷新时报错 有很多可能原因,需要根据事件的具体描述具体问题具体分析 Refresh Lock Error 12 数据库刷新过程中遇到锁异 有很多可能原因,需要根据事件的具体描述具体问题具体分析 第 81 页 共 182 页 常 Tuple Mover Error 13 数据库在尝试移动 WOS 数据 到 ROS 遇到异常 有很多可能原因,需要根据事件的具体描述具体问题具体分析 Timer Service Task Error 14 内部调度任务遇到异常 仅供内部使用 Stale Checkpoint 15 WOS 中的数据未能及时的移 出,不安全停机可能需要重 新加载大量数据 检查 vertica.log 看 moveout 操作是否都是成功的 Vertica.log 事件会自动捕获并报告,ACTIVE_EVENTS 会报告正在打开的事件,下面简单讲述配置 syslog 工具的事件报告方法。为了让 vertica 事件报告到 syslog 中,须对需要报告的 vertica 事件做单独设置,默认情 况下事件写入到/var/log/messages 文件中。配置过程如下:  Vertica 数据库中启用对 syslog 的事件捕获  定义需要捕获的事件,vertica 强烈建议捕获检查点过久事件  定义需要使用的 syslog 工具 #启用 syslog 捕获事件 $ SELECT SET_CONFIG_PARAMETER('SyslogEnabled', 1 ); SET_CONFIG_PARAMETER ---------------------------- Parameter set successfully (1 row) $ SELECT SET_CONFIG_PARAMETER('SyslogEnabled', 0 ); SET_CONFIG_PARAMETER ---------------------------- Parameter set successfully (1 row) #设置需要 syslog 捕获的事件 => SELECT SET_CONFIG_PARAMETER('SyslogEvents', 'Event_Name' , 'Event_Name'); SET_CONFIG_PARAMETER ---------------------------- Parameter set successfully (1 row) #设置 syslog 捕获事件的报告工具 => SELECT SET_CONFIG_PARAMETER('SyslogFacility' , 'Facility_Name'); 第 82 页 共 182 页 其中 Facility_Name 可以是下表所列之一 工具名 工具 auth uucp (UUCP subsystem) authpriv (Linux only) local0 (local use 0) cron local1 (local use 1) daemon local2 (local use 2) ftp (Linux only) local3 (local use 3) lpr (line printer subsystem) local4 (local use 4) mail (mail system) local5 (local use 5) news (network news subsystem) local6 (local use 6) 8.3 数据收集器 Vertica 的监控数据大部分是通过数据收集器(Data Collector)来完成的,DC 默认是启用的,收集所有用 户的信息,在出现性能问题之后可以由超级用户关掉。 #关闭 DC 数据收集 SELECT SET_CONFIG_PARAMETER('EnableDataCollector', '0'); #打开 DC 数据收集 SELECT SET_CONFIG_PARAMETER('EnableDataCollector', '1'); DC 的每个组件都有相应的数据保存策略,具体可以通过函数 GET_DATA_COLLECTOR_POLICY()来查询, 查询时需要提供组件名称,而组件名称可以通过字典表 V_MONITOR.DATA_COLLECTOR 获得,如果需要对某 个组件的数据保存策略进行单独设定时,通过函数 SET_DATA_COLLECTOR_POLICY()来实现。 #设置某一组件的数据保存策略 SET_DATA_COLLECTOR_POLICY('component', 'memoryKB', 'diskKB' ) #查询组件名称 SELECT DISTINCT component, description FROM data_collector ORDER BY 1 ASC; 每次启动 DC 会自动在/catalog 目录创建 DC 相应的目录,DC 以..log 格式保 第 83 页 共 182 页 存所收集数据的日志在磁盘上,所以同一时间可能有很多日志。另外每次启动 vertica 会同时创建另外两个文件 CREATE__TABLE.sql 和 COPY__TABLE.sql,分布实现创建 DC 数据收集表和 加载相应的数据。 Vertica 提供了两个函数操作这些日志,即 CLEAR_DATA_COLLECTOR()和 FLUSH_DATA_COLLECTOR(),分别用以清理组件日志内容、系统表 V_MONITOR.DATA_COLLECTOR 信 息和同步内存和磁盘数据。这两个函数都可以指定组件处理和不指定组件情况下处理所有组件。 #清理指定组件或者整个节点的数据 => SELECT clear_data_collector('ResourceAcquisitions'); clear_data_collector ---------------------- CLEAR (1 row) => SELECT clear_data_collector(); clear_data_collector ---------------------- CLEAR (1 row) #刷新指定组件或者整个节点的数据 => SELECT flush_data_collector(); flush_data_collector ---------------------- FLUSH (1 row) => SELECT flush_data_collector('ResourceAcquisitions'); flush_data_collector ---------------------- FLUSH (1 row) DC 提供了一些以 dc_开头的内部表,这些内部表存储在 v_internal schema 下面,由于这些对象是不对外 公开的,vertica 可能在没有任何通知的情况下修改和删除,所以不建议在脚本或者监控工具中使用,vertica 建 议使用 WLA 替代查询 DC 内部表。 无论 refresh 操作成功或者失败,PROJECTION_REFRESHES 系统表都会记录,直到遇到 CLEAR_PROJECTION_REFRESHES()或者表的磁盘配额超出,字段 IS_EXECUTING 返回 refresh 的运行状 态 t:正在运行,f:之前运行过,CLEAR_PROJECTION_REFRESHES()清除状态为 f 的记录。 8.4 工作负载分析器(WLA) 工作负载分析器(Workload Analyzer)智能的监控 SQL 语句、负载历史、资源、配置以便查找查询性能 问题的原因,WLA 会提供一系列优化建议,这些建议是基于联合系统统计信息、系统事件、表/projection 的设 第 84 页 共 182 页 计而得出的,所以它能让用户可以非常轻松的优化查询性能而不一定具有复杂的技能。 Vertica 通过 ANALYZE_WORKLOAD()实现分析数据库对象表或者 schema 的负载情况,并给出最优化建 议。 #语法格式 1 ANALYZE_WORKLOAD ( 'scope' , 'since_time' ); => SELECT ANALYZE_WORKLOAD('t1', TIMESTAMP '2010-10-04 11:18:15'); => SELECT ANALYZE_WORKLOAD('t1', '2010-10-04 11:18:15'::TIMESTAMPTZ); => SELECT ANALYZE_WORKLOAD('t1', 'October 4, 2010'::TIMESTAMP); => SELECT ANALYZE_WORKLOAD('t1', '10-04-10'::TIMESTAMPTZ); #语法格式 2,记录分析历史 ANALYZE_WORKLOAD ( 'scope' , [ true ] ); => SELECT ANALYZE_WORKLOAD('', true); #分析所有数据库对象 dbadmin=> SELECT ANALYZE_WORKLOAD(''); -[ RECORD 1 ]----------+------------------------------------------------------------ observation_count | 1 first_observation_time | last_observation_time | tuning_parameter | SyslogEnabled tuning_description | reset configuration parameter with set_config_parameter() tuning_command | select set_config_parameter('SyslogEnabled', '') tuning_cost | LOW #分析最近 2 天/1 周的问题 => SELECT ANALYZE_WORKLOAD('', NOW() - '2 DAYS'::INTERVAL); dbadmin=> SELECT ANALYZE_WORKLOAD('', NOW() - INTERVAL '1 week'); -[ RECORD 1 ]----------+------------------------------------------------------------ observation_count | 1 first_observation_time | last_observation_time | tuning_parameter | SyslogEnabled tuning_description | reset configuration parameter with set_config_parameter() tuning_command | select set_config_parameter('SyslogEnabled', '') tuning_cost | LOW #查询优化建议 dbadmin=> SELECT * FROM tuning_recommendations; -[ RECORD 1 ]----------+------------------------------------------------------------ observation_count | 1 first_observation_time | 第 85 页 共 182 页 last_observation_time | tuning_parameter | SyslogEnabled tuning_description | reset configuration parameter with set_config_parameter() tuning_command | select set_config_parameter('SyslogEnabled', '') tuning_cost | LOW 一般情况下 vertica 能够根据系统监控和信息统计生存优化建议报告,当然在某些特定情况下,WLA 给出的 优化方案可能无法解决问题,需要结合问题触发的环境具体分析。 8.5 诊断工具 - scrutinize Vertica 诊断工具 scrutinize 提供了收集集群间大范围的诊断信息的手段,可以包含如下信息  主机的诊断信息和配置信息  集群的运行状态信息  数据库的安装进程日志、数据库日志、admintools 日志(如 vertica.log, dbLog, admintools.log)  Vertica log  重要的错误信息  数据库 schema 信息  结构化的 event 信息  License size  系统表信息,如系统、资源、负载、性能相关信息  数据字典元数据信息  备份信息 #scrutinize 收集诊断信息 [dbadmin@V2 ~]$ /opt/vertica/bin/scrutinize Vertica Scrutinize Report ----------------------------- Result Dir: /home/dbadmin/VerticaScrutinize.20140820160435 User: dbadmin Database: vertica Password: --输入密码,不回显 Initiator node: v_vertica_node0002 Running remote worker on v_vertica_node0002 @ /tmp/VerticaScrutinizeLocal.20140820160435/v_vertica_node0002 第 86 页 共 182 页 Running remote worker on v_vertica_node0001 @ /tmp/VerticaScrutinizeLocal.20140820160435/v_vertica_node0001 Running remote worker on v_vertica_node0003 @ /tmp/VerticaScrutinizeLocal.20140820160435/v_vertica_node0003 Cleaning up on node v_vertica_node0001 (10.75.7.110) Cleaning up on node v_vertica_node0002 (10.75.7.111) Cleaning up on node v_vertica_node0003 (10.75.7.112) Gathered diagnostics for Customer: Vertica Community Edition Database designation: NICE NICKEL Timestamp: 20140820160435 All output including logs stored in /home/dbadmin/VerticaScrutinize.20140820160435.zip 该命令还可以使用下表所示参数: 参数 描述 --help, -h 显示帮助信息 -X LIST, --exclude-tasks=LIST [ all | n ] 使用--exclude-tasks 忽略部分类型的信息收集,默认情况下收集所有信息。  DC—Data Collector tables  File—Log files from the installation process, the database, and the administration tools (such as, vertica.log, dbLog, admintools.log)  VerticaLog—HP Vertica logs  CatalogObject—HP Vertica catalog metadata, such as system configuration parameters  SystemTable—HP Vertica system tables that contain information about system, resources, workload, and performance  Query—HP Vertica meta functions that use vsql to connect to the database, such as EXPORT_CATALOG()  Command—Operating system information, such as the length of time a node has been up  all—All default tasks -v, --vsql-off Excludes Query and SystemTable tasks, which are used to connect to the database. Consider using --vsql-off if HP Vertica is running but is slow to respond. If you haven't created a database but need help troubleshooting other cluster issues, use --vsql-off. This argument can be helpful for dealing with problems during an upgrade. -s, --local_diags [Default all hosts] Gathers diagnostics for the specified host. -d DB, --database=DB Gathers diagnostics for the specified database. If your database has a password, you must also supply the -P PASSWORD argument. If you omit the --database argument, scrutinize collects diagnostics on the running database. Otherwise:  If no database is running but that database is defined in the Administration Tools 第 87 页 共 182 页 metadata, scrutinize collects diagnostics on the stopped database.  If more than one database is defined but none is running, scrutinize returns an error. You must supply the --database argument for the appropriate database.  If multiple databases are running (unsupported in production environments), scrutinize returns an error. Only one database can be running during diagnostics collection. Tip: Always use the --database argument if you have more than one database defined on the cluster. -n HOST_LIST, --hosts=HOST_LIST [Default: all cluster hosts] Gathers diagnostics for the specified hosts. -m MESSAGE, --message=MESSAGE [Default: no message] Includes a message in the diagnostics output file, such as the reason for gathering/submitting diagnostics. You can also include a support-supplied case number and other information to help your HP Vertica Technical Support contact troubleshoot your case. There is no character limit. The --message argument accepts the following inputs:  --message "my message"  --message PROMPT  --message "/path/to/file" See scrutinize Examples for different inputs using the --message argument. -o OUTPUT_DIR, --output_dir=OUTPUT_DIR [Default: current directory] Redirects output to a location that is not the current directory. -U USERNAME, --user=USERNAME [Default: current user] Specifies the database user scrutinize requires if the HP Vertica administrative user is different from the operating system dbadmin user. For example, you might have specified a name different from the default dbadmin user when you installed HP Vertica. -P PASSWORD, --password=PASSWORD [Default: no password] Specifies the database password, which is required if your database has a password. If you omit this argument on a password-protected database, scrutinize fails with a run-time error. Note: You must include the --password argument if the HP Vertica administrator account (default dbadmin, set during an HP Vertica installation) has a non-blank password. You can omit the --database argument if the database is running or if there is only one database defined on the cluster. Otherwise, you must include the --database argument with the -- password argument. -t TYPE, --type=TYPE Specifies the type of diagnostics collection to perform. Options are:  basic – [Default] Omit profiling data  profiling – Gather profiling data  context – Gather important data -T TASKS, --tasks=TASKS In collaboration with your HP Vertica Technical Support contact, use the --tasks argument to instruct scrutinize to gather diagnostics for one or more specified tasks in a file or JSON list. --tmpdir=TMP_DIR [Default: /tmp] Specifies the temp directory to use on all nodes. -U URL, --url=URL [Default: none (do not upload)] Posts output of diagnostics collection to an HP Vertica support-provided URL, which can be http or ftp. You need a user name and password to upload the file. 第 88 页 共 182 页 -z NUMGZ, --include_gzlogs=NUMGZ [ all | n ] [Default: 1] Includes n number of gzipped vertica.log-*.gz files within the VerticaScrutinize file. To collect all logs, specify 'all.' -A URL, --auth-upload=URL Collects and uploads your company name from your HP Vertica license so Technical Support can verify your identity. The authenticated upload argument requires a valid HP Vertica license. Unlike the --url upload argument, --auth-upload does not require a user name and password to upload your file. Note: HP Vertica Technical Support provides you with the URL or FTP address to upload the file. 尽管 scrutinize 不需要数据库启动状态,但是在数据库启动状态下能收集数据库相关的一些信息,但是对数 据库的影响却很小。如果不希望对在线系统造成影响,可以通过指定某些参数忽略部分收集,如--vsql-off 避免 和数据库的连接。 8.6 诊断工具 - diagnostics diagnostics 收集数据库和主机的配置信息,并把他们保存到一个.zip 文件中。 参数 描述 -h --help Shows a help message that contains all commands for the diagnostics utility and exits. -l --listdbs Lists running and non-running databases. -s --local_diags Gathers diagnostics for local host only. -d dbname--database dbname Gathers information about the specified database. -o OUTPUT_DIR--output_dir OUTPUT_DIR Redirects output to a location other than the default /opt/vertica/log. -n HOST_LIST,--hosts HOST_LIST Gathers diagnostics for the specified hosts. -z [ all | n ] Specifies how many vertica.log.*.gz files to include in diagnostics. The default is 1. #列出所有运行和非运行状态的数据库 [dbadmin@V2 ~]$ /opt/vertica/bin/diagnostics -l Running Diagnostics as user: dbadmin Vertica Diagnostics Report ----------------------------- Using VSQL: /opt/vertica/bin/vsql Result Dir: /opt/vertica/log/VerticaDiagnostics.20140820172653 Listing databases... Running database: vertica 第 89 页 共 182 页 All results are stored in /opt/vertica/log/VerticaDiagnostics.20140820172653.zip 8.7 诊断工具 - collect_diag_dump.sh 诊 断 工 具 脚 本 collect_diag_dump.sh 从运行的数据库收集系统表、设计、执行计划对象到一个命名 为./diag_dump_.tar.gz 的,如果运行中没有输入参数,则需要数据库 dbadmin 的密码。 /opt/vertica/scripts/collect_diag_dump.sh [ command... ] -U User name, typically the database administrator account, dbadmin. -w Database password. -c Includes a compression analysis, resulting in a longer script execution time. # /opt/vertica/scripts/collect_diag_dump.sh -U dbadmin -w password -c 9. 权限和安全 当数据库对象被创建的时候,诸如 SCHEMA、TABLE、VIEW 等都会分配一个属主,即是执行创建命令的 用户。默认情况下对象的使用权限只有数据库超级用户和对象的属主有该对象所有相关的权限。为了使用对象或 者避免已授权用户再使用对象,需要对已获准的用户进行授权和对已授权的用户进行权限收回。 对象的权限通过 GRANT/REVOKE 进行分配和收回操作,下表显示数据库各种对象相关的权限: 数据库通过特殊角色 PUBLIC 为所有数据库用户分配最小化的权限,该角色自动启用。数据库管理员或者其 它超级用户可以通过 GRANT 授予用户更高的权限。 第 90 页 共 182 页 另外 MANAGEMENT CONSOLE 的权限是通过角色控制的,MC 的权限不会覆盖或者改变系统的权限。 9.1 普通操作权限 除非特别说明数据库超级用户拥有数据库相关的所有的权限,对象的属主拥有对象相关的所有权限。 9.1.1 SCHEMA 权限 任何新建的 vertica 数据库都有一个叫 PUBLIC 的 SCHEMA,而新建的用户都只有 PUBLIC 的 USAGE 权 限。数据库超级用户可以通过显式的授予一个用户 create 权限,如同授予单独的对象权限一样,新建用户可以在 PUBLIC 上进行创建表等操作。 总结起来 SCHEMA 有如下权限: CREATE SCHEMA 数据库上的 CREATE 权限 Drop SCHEMA SCHEMA 的属主 ALTER SCHEMA RENAME 数据库上的 CREATE 权限 SCHEMA 上创建对象 SCHEMA 的 USAGE 权限 创建 SCHEMA 的语法如下所示: CREATE SCHEMA [ IF NOT EXISTS ] [db-name.]schema [ AUTHORIZATION user-name ] 其中[ IF NOT EXISTS ]为可选子句,用以提示当创建的 SCHEMA 存在时系统提示 NOTICE 信息或者 ERROR 信息,但是不管哪种方式当 SCHEMA 已存在时都不会再创建。 [db-name.]可选子句,用以指示当前的数据库名,前提是必须连接到指定的数据库。 Schema 必选子句,要创建的 SCHEMA 名称。 AUTHORIZATION user-name 可选子句,用以分配 SCHEMA 的属主,如果未指定则属主为创建 SCHEMA 的用户。只有超级用户创建的 SCHEMA 的属主可以创建者不同。 创建 SCHEMA 的语句可以包含在该 SCHEEMA 上建表的子句或者授权子句,如下所示: #创建 SCHEMA 并创建表 dbadmin=> CREATE SCHEMA s1 CREATE TABLE t1 (c INT); CREATE SCHEMA dbadmin=> select * from s1.t1; c --- (0 rows) dbadmin=> insert into s1.t1 values(1); OUTPUT -------- 1 (1 row) dbadmin=> commit; 第 91 页 共 182 页 COMMIT 一个用户可以通过 grant 语句授予 schema 的下面两个权限:  CREATE:在 SCHEMA 上创建新对象的权限,包括新建一个对象、重命名一个对象、把对象移 动到别的 SCHEMA 的操作。  USAGE:SCHEMA 上对象的查询、访问、修改、删除的权限,可能需要同时授予对象相关的权 限,如 SELECT 等。 新建用户默认没有 public 模式的 USAGE 权限,一般情况下要给用户 public 模式的 USAGE 权限。同时可 能还要给予用户相应模式的合适权限。授权命令为: GRANT { ... { CREATE | USAGE } [ , ... ] ... | ALL [ PRIVILEGES ] } ... ON SCHEMA [db-name.]schema [ , ... ] ... TO { username | role | PUBLIC } [ , ... ] ... [ WITH GRANT OPTION ] 参数 含义 CREATE 运行用户读取模式中的对象和在模式中创建表和视图的权限 USAGE 允许用户访问模式中的对象,用户必须同时被授予对象相关的权限 All 所有权限 PRIVILEGES 为了标准 SQL 的兼容,忽略 [db-name.]schema 要授权的模式及其所在数据库,数据库名可忽略 Username| role| PUBLIC 被授予权限的用户、角色、或者 public 角色 WITH GRANT OPTION 是否允许用户再对其它人授权 9.1.2 创建表权限 Vertica 表相关的权限通过下表汇总显示: 操作 所需权限 CREATE TABLE SCHEMA 上的 CREATE 权限 第 92 页 共 182 页 提示:如果创建表要引用 sequence,则创建表的语句还需要下面的权限 Sequence 的 SELECT 权限 Sequence 的 SCHEMA 的 USAGE 权限 DROP TABLE 表所在 SCHEMA 的 USAGE 权限,或者 SCHEMA 的属主 TRUNCATE TABLE 表所在 SCHEMA 的 USAGE 权限,或者 SCHEMA 的属主 表属主或者超级用户才能操作 truncate ALTER TABLE ADD/ DROP / RENAME / ALTER-TYPE COLUMN 表所在 SCHEMA 的 USAGE 权限 ALTER TABLE ADD/DROP CONSTRAINT 表所在 SCHEMA 的 USAGE 权限 ALTER TABLE PARTITION (REORGANIZE) 表所在 SCHEMA 的 USAGE 权限 ALTER TABLE RENAME 表所在 SCHEMA 的 USAGE 和 CREATE 权限 ALTER TABLE SET SCHEMA 表的新 SCHEMA 的 CREATE 权限 表的旧 SCHEMA 的 USAGE 权限 SELECT 表所在 SCHEMA 的 USAGE 权限 表的 SELECT 权限 INSERT 表所在 SCHEMA 的 USAGE 权限 表的 INSERT 权限 DELETE 表所在 SCHEMA 的 USAGE 权限 表的 DELETE 权限 通过 WHERE 或者 SET 所关联表的 SELECT 权限 UPDATE 表所在 SCHEMA 的 USAGE 权限 表的 UPDATE 权限 通过 WHERE 或者 SET 所关联表的 SELECT 权限 REFERENCES 包含约束的表和外键的源表所在 SCHEMA 的 USAGE 权限 创建外键约束需要参考表的 REFERENCES 权限 ANALYZE_STATISTICS() 表所在 SCHEMA 的 USAGE 权限 表的 INSERT/UPDATE/DELETE 权限 ANALYZE_HISTOGRAM() 表所在 SCHEMA 的 USAGE 权限 表的 INSERT/UPDATE/DELETE 权限 DROP_STATISTICS() 表所在 SCHEMA 的 USAGE 权限 第 93 页 共 182 页 表的 INSERT/UPDATE/DELETE 权限 DROP_PARTITION() 表所在 SCHEMA 的 USAGE 权限 MERGE_PARTITIONS() 表所在 SCHEMA 的 USAGE 权限 创建表的语法如下所示: CREATE TABLE [ IF NOT EXISTS ] [[db-name.]schema.]table-name { ... ( Column-Definition (table) [ , ... ] ) ... | [ table-constraint ( column_name, ... )] ... | [ column-name-list (create table) ] AS [COPY] [ [ AT EPOCH LATEST ] ... | [ AT TIME 'timestamp' ] ] [ /*+ direct */ ] query ... | [ LIKE [[db-name.]schema.]existing-table [ {INCLUDING | EXCLUDING} PROJECTIONS ] ]} ... [ ORDER BY table-column [ , ... ] ] ... [ ENCODED BY column-definition [ , ... ] ... [ Hash-Segmentation-Clause ... | UNSEGMENTED { NODE node | ALL NODES } ] ... [ KSAFE [k_num] ] ... [ PARTITION BY partition-clause ] 下表详细解释建表所有相关参数的含义: 参数 参数含义 [ IF NOT EXISTS ] 为可选子句,用以提示当创建的表存在时系统提示 NOTICE 信息或者 ERROR 信息,但是不管哪种方式当表已存在时都不会再创建。 [[db-name.]schema.] 可选子句,用于指定数据库名和模式名,如果在当前的查询路径上对象名不唯一 可以通过 db-name.加以限定,前提是必须连接到指定的数据库。 如果不指定模式,表自动创建在用户的默认模式中。默认模式是查找路径中 的第一个模式,可以通过命令 SHOW SEARCH_PATH 获取 table-name 表名 column-definition 列定义 column-name-list 当使用 CREATE TABLE AS SELECT 创建时重新命名列名 AT EPOCH LATEST | AT TIME'timestamp' 通过 AS 子句进行历史数据查询。 可以使用 AT EPOCH LATEST 去包含新提交的事务数据或者指定基于时间戳的 EPOCH。 第 94 页 共 182 页 外部表不能使用其中的任何一项。 /*+ direct */ 数据不通过 WOS 直接写入 ROS,以下都是有效的提示。 /*+direct*/ /* + direct*/ /*+ direct*/ /*+direct */ AS query 通过查询结果创建新表并填充数据 CREATE TABLE promo AS SELECT ... ; 对列进行重命名 CREATE TABLE promo (name, address, ...) AS SELECT customer_name, customer_address ... ; Flex 表不支持 AS 子句 如果查询返回了 0 宽度的列,那么列的类型自动转化成 VARCHAR(80) [LIKE existing-table [INCLUDING | EXCLUDING PROJECTIONS]] 复制一张已有表到新表,flex 表不支持 LIKE 子句,临时表不支持 INCLUDING PROJECTIONS 子句。 可选的 INCLUDING PROJECTIONS 子句用于创建当前表上非 pre-join 的 Projection,如果表有相应的存储策略会一并复制,默认值时 EXCLUDING PROJECTIONS。 [ ORDER BY table-column ] 为可选子句,用于指定表上默认的 supperprojection 的排序方式,数据仅以升 序方式排序,如果不指定,则 vertica 根据列在定义时出现的顺序进行排序。 该选项不能用于外部表 ENCODED BY column-definition 只用于[CREATE TABLE AS SELECT] 为列指定编码方式 如果通过 AS SELECT 创建表并重命名列时,该编码方式也适用于重命名列 hash-segmentation-clause 为可选子句,用于指定表的 supperprojection 的数据能跨节点平均的分布方式 UNSEGMENTED{ NODE node | ALL NODES } 为可选子句,用于不对 Projection 进行分段,默认是不对当前节点上的 Projection 进行分段,可以指定以下两种参数: NODE node 对指定节点创建非分段的 Projection,小表的 Projection 必须用 UNSEGMENTED。 ALL NODES 自动创建和复制 Projection, KSAFE [ k ] 用于指定表是否 ksafe 以及 ksafe 的值 PARTITION BY partition- clause 指定表分区方式,对 AS SELECT 类型语句不适用,但需要满足以下要求 第 95 页 共 182 页 分区子句必须对单个非空列进行计算,可以参考多列,但是每行必须返回单个值 所有叶子表达式要么是约束要么是表的列 所有其它表达式必须是函数或者操作符,聚合函数和查询是不允许的 表达式中使用的 SQL 函数结果必须是不可变的 如果在创建表的时候未指定 Projection 相关子句,当进行 insert、copy 等数据加载操作时 vertica 自动为表 创建 supperprojection, supperprojection 创建在和表相同的模式中。 如果使用 CREATE TABLE AS SELECT 方式创建表,表创建之后一个使用查询部分属性的 Projection 也 随之创建。 如果使用下述参数中的任何一个,一个使用这些指定属主的 Projection 自动创建,这些参数包含:ENCODED BY column-definition 、 ORDER BY table-column 、 hash-segmentation-clause 、 UNSEGMENTED { NODE node | ALL NODES }、KSAFE 对表进行授权的命令: GRANT { { SELECT | INSERT | UPDATE | DELETE | REFERENCES } [ ,... ] ... | ALL [ PRIVILEGES ] } ... ON [ TABLE ] [ [ db-name.]schema.]tablename [ , ... ] ... | ON ALL TABLES IN SCHEMA schema-name [, ...] ... TO { username | role | PUBLIC } [ , ... ] ... [ WITH GRANT OPTION ] 参数 含义 SELECT | UPDATE | DELETE 允许查询指定查询、更新、删除指定表,如果 UPDATE|DELETE 带 where 子 句,则还需要 SELECT 权限 INSERT 允许插入数据到指定表,COPY FROM STDIN 需要权限和 INSERT 相同, COPY FROM 是只允许管理员进行的操作 [db-name.]schema 要授权的模式及其所在数据库,数据库名可忽略 Tablename | ON ALL TABLES IN SCHEMA 指定授权表或者模式下所有的表 Username| role| PUBLIC 被授予权限的用户、角色、或者 public 角色 WITH GRANT OPTION 是否允许用户再对其它人授权 第 96 页 共 182 页 9.1.3 创建视图权限 CREATE VIEW 对象所在 SCHEMA 的 USAGE 和 CREATE 权限 所依赖对象的 SELECT 权限 DROP VIEW 对象所在 SCHEMA 的 USAGE 权限,或者 SCHEMA 的属主 SELECT ... FROM VIEW 对象所在 SCHEMA 的 USAGE 权限 VIEW 的 SELECT 权限 VIEW 所依赖的基表的必须被直接授予,不能通过角色 VIEW 的属主必须授予对基表的 SELECT ... WITH GRANT OPTION 权 限,VIEW 的使用者必须被授予 SELECT 权限 对表进行授权的命令: GRANT ... { SELECT | ALL [ PRIVILEGES ] } ... ON [ [ db-name.]schema.]viewname [, ...] ... TO { username | role | PUBLIC } [, ...] ... [ WITH GRANT OPTION ] 参数 含义 SELECT | ALL 允许查询指定查询、更新、删除指定表,如果 UPDATE|DELETE 带 where 子 句,则还需要 SELECT 权限 INSERT 允许插入数据到指定表,COPY FROM STDIN 需要权限和 INSERT 相同, COPY FROM 是只允许管理员进行的操作 [db-name.]schema 要授权的模式及其所在数据库,数据库名可忽略 Tablename | ON ALL TABLES IN SCHEMA 指定授权表或者模式下所有的表 Username| role| PUBLIC 被授予权限的用户、角色、或者 public 角色 WITH GRANT OPTION 是否允许用户再对其它人授权 9.1.4 创建 Projection 权限 CREATE PROJECTION 对象所在 SCHEMA 的 USAGE 和 CREATE 权限 第 97 页 共 182 页 所依赖对象的 SELECT 权限 如果是在创建表的时候隐含创建的 Projection 不需要比建表更多的权限 AUTO/DELAYED PROJECTION 在进行 INSERT..SELECT or COPY 创建 Projection 对象所在 SCHEMA 的 USAGE 权限 基表的 SELECT 权限 ALTER PROJECTION RENAME 对象所在 SCHEMA 的 USAGE 和 CREATE 权限 DROP PROJECTION 对象所在 SCHEMA 的 USAGE 权限 9.1.5 创建序列的权限 CREATE SEQUENCE 对象所在 SCHEMA 的 CREATE 权限 如果是在创建表的时候引用的序列需要基表的 SELECT 权限和序列所在 SCHEMA 的 CREATE 权限 CREATE TABLE with SEQUENCE 对象所在 SCHEMA 的 USAGE 权限 序列的 SELECT 权限 DROP SEQUENCE 对象所在 SCHEMA 的 USAGE 权限,或者 SCHEMA 的属主 ALTER SEQUENCE RENAME TO 对象所在 SCHEMA 的 USAGE 和 CREATE 权限 ALTER SEQUENCE SET SCHEMA 对象所当前在 SCHEMA 的 USAGE 权限 对象所在新的 SCHEMA 的 CREATE 权限 CURRVAL()NEXTVAL() 对象所在 SCHEMA 的 USAGE 权限 序列的 SELECT 权限 对序列进行授权的命令: GRANT { SELECT | ALL [ PRIVILEGES ] }... ON SEQUENCE [[db-name.]schema.]sequence-name [ , ... ] ... | ON ALL SEQUENCES IN SCHEMA schema-name [, ...] ... TO { username | role | PUBLIC } [ , ... ] ... [ WITH GRANT OPTION ] 参数 含义 第 98 页 共 182 页 SELECT | ALL 允许查询指定 sequence 的 CURRVAL() and NEXTVAL() sequence-name | ON ALL SEQUENCES IN SCHEMA 指定授权的序列名,或者模式下所有序列 [db-name.]schema 要授权的模式及其所在数据库,数据库名可忽略 Username| role| PUBLIC 被授予权限的用户、角色、或者 public 角色 WITH GRANT OPTION 是否允许用户再对其它人授权 9.1.6 IO 操作权限 CONNECT/DISCONNECT NONE EXPORT TO HP Vertica 源表的 SELECT 权限 源表所在 SCHEMA 的 USAGE 权限 目标数据库目标表的 INSERT 权限 目标表所在 SCHEMA 的 USAGE 权限 COPY FROM HP Vertica 源表的 SELECT 权限 源表所在 SCHEMA 的 USAGE 权限 目标数据库目标表的 INSERT 权限 目标表所在 SCHEMA 的 USAGE 权限 COPY FROM file 超级用户 COPY FROM STDIN 表的 INSERT 权限 表所当 SCHEMA 的 USAGE 权限 COPY LOCAL 表的 INSERT 权限 表所当 SCHEMA 的 USAGE 权限 9.1.7 过程和函数权限 外部存储过程只有超级用户有权限创建和删除,一般用户甚至没有执行权限。如果用户需要执行外部过程, 可以授权其 EXECUTE 权限,同时还需要授权过程所在模式的 USAGE 权限。 而对象用户自定义的函数,其可以有用户创建,创建者需要有所在模式的 CREATE 权限。其它用户如果需要执 第 99 页 共 182 页 行这些函数,则需要被授予这些函数的 EXECUTE 权限,同时还需要授权函数所在模式的 USAGE 权限。 9.2 角色权限 角色是一系列权限的集合,通过角色可以使用权限的管理变的简单。角色可以被分配给一个或者多个用户, 被分配角色的用户要使用角色中的权限必须启用角色。 可以通过角色建立起角色的层级,通过角色的授权不会覆盖直接的授权。使用角色一般参考以下过程: 创建角色;把对象的权限授权给角色;把角色授权给用户或者角色;获得授权的用户通过 set role 使用角色。 Vertica 数据库默认有以下几个角色,默认角色不能被改名或修改、删除,除了 public 角色以外其它角色不 能被授予额外的角色,但是这些角色可以授权给其它用户和角色,另外单独的权限可以被授予到这些角色上:  PUBLIC:默认创建并自动分配给每个新建用户,可以把每个用户都拥有的权限授权给 public, 它不能被回收。  PSEUDOSUPERUSER:默认创建,超级用户或者拥有该角色的人可以将其授权给别的用户或 角色。启用该角色的用户拥有数据库超级用户的所有权限,包括:创建模式;创建和对角色授权; 忽略所有 grant、revoke 的认证;设置用户的密码;锁定用户;创建、删除 UDF 库和函数;创 建、删除外部过程;添加、编辑节点的备注;创建、删除密码的 profile;  DBADMIN:主要拥有以下权限:创建、删除用户和模式以及角色;查询所有系统表;查看、结 束用户进程。但是它没有启停数据库;修改 DBADMIN;修改配置文件 (set_config_parameter)的权限。  DBDUSER:主要运行非 DBA 用户访问 Database Designer 使用命令行函数 重要提示:对于 DBADMIN 用户和被授予 DBUSER 角色的用户,要确保分配一个资源池,以便在运行 DB Designer 时管理其资源。DB Designer 可以多个用户并发执行,而相互之间不影响,但是可能会挤占系统的资 源。 默认情况下会话没有被启用的角色,超级用户可以给用户设置一个或者多个默认的角色,这些角色在会话开 始便被启用。通过 ALTER USER 的 DEFAULT ROLE 命令来实现。 需要说明的是,只有已获得访问权限的角色可以被设置为默认的角色;和授权不同,设置一个或多个角色为 默认角色会覆盖之前的设定;如果需要清除默认角色的设定使用 NONE;默认角色只在会话开始时生效,不影响 当前会话已经启用的角色;避免授予用户管理性或者破坏性的角色,强制用户显式的启用这样的角色可以避免一 些故障或者数据丢失的事件发生。 如果希望角色授予用户后,该用户还可以把角色授权给别人,则需要在授权时使用 WITH ADMIN OPTION。 和普通权限的 WITH GRANT OPTION 类似,WITH ADMIN OPTION 可以单独收回,或者通过收回权限一并收 回。 除了默认角色以外,角色需要被启用之后才能使用,启用方法是使用 SET ROLE 命令,可以指定要启用的角 色,或者指定 ALL 启用该用户有访问权限的所有角色。一个用户启用角色不影响任何其它用户使用该角色,查看 第 100 页 共 182 页 启用了哪些角色使用 SHOW ENABLED_ROLES,查看可以使用的角色使用 SHOW AVAILABLE_ROLES。清 除已启用的角色使用 NONE。 查询角色相关的授权可以通过系统表 roles 获得,带*表示带有 ADMIN OPTION。 dbadmin=> SELECT * FROM roles; role_id | name | assigned_roles -------------------+-----------------+---------------- 45035996273704964 | public | 45035996273704966 | dbduser | 45035996273704968 | dbadmin | dbduser* 45035996273704970 | pseudosuperuser | dbadmin* 49539595901498772 | reviewer | (5 rows) 通过函数 HAS_ROLE()可以检查某一用户是否具有某一角色,不指定用户名时检查当前用户自己是否具有该 角色,超级用户可以使用用户名参数指定某一用户是否具有某一角色。 dbadmin=> select HAS_ROLE('DBADMIN'); HAS_ROLE ---------- t (1 row) dbadmin=> select HAS_ROLE('LIZY','DBADMIN'); HAS_ROLE ---------- t (1 row) dbadmin=> SHOW ENABLED_ROLES; name | setting ---------------+-------------------------------------- enabled roles | dbduser*, dbadmin*, pseudosuperuser* (1 row) 另外通过系统表 USERS 也可以查询用户相关的角色,参考字段为 all_roles、default_roles。 dbadmin=> select * from users; -[ RECORD 1 ]-----+-------------------------------------------------- user_id | 45035996273704962 user_name | dbadmin is_super_user | t profile_name | default 第 101 页 共 182 页 is_locked | f lock_time | resource_pool | general memory_cap_kb | unlimited temp_space_cap_kb | unlimited run_time_cap | unlimited all_roles | dbduser*, dbadmin*, pseudosuperuser* default_roles | dbduser*, dbadmin*, pseudosuperuser* search_path | -[ RECORD 2 ]-----+-------------------------------------------------- user_id | 45035996273988370 user_name | vertica is_super_user | f profile_name | default is_locked | f lock_time | resource_pool | general memory_cap_kb | unlimited temp_space_cap_kb | unlimited run_time_cap | unlimited all_roles | default_roles | search_path | "$user", public, v_catalog, v_monitor, v_internal 9.3 权限的管理 9.3.1 用户权限管理 当一个用户授权 all 权限给某一用户时,该语句总是成功,当授权时带 WITH GRANT OPTION 子句,则只 有授权者拥有 WITH GRANT OPTION 权限的会授予被授权者。 一般情况下只有授予权限则才有权限收回已授予的权限,授权者一般是超级用户或者拥有对象相应权限的 WITH GRANT OPTION 权限以及 SCHEMA 的 USAGE 权限。使用 REVOKE 回收权限时可以通过收回权限同 时收回 WITH GRANT OPTION 权限,也可以单独收回 WITH GRANT OPTION 权限。 如果用户的 WITH GRANT OPTION 权限被收回,则被该用户通过 WITH GRANT OPTION 授予的权限也必 须一并收回,即收回时使用 cascade 子句。 #授予和收回 grant option => GRANT INSERT on applog TO Bob WITH GRANT OPTION; GRANT PRIVILEGE => REVOKE GRANT OPTION FOR INSERT ON applog FROM Bob; REVOKE PRIVILEGE #创建用户和进行授权 dbadmin=> CREATE USER User1; 第 102 页 共 182 页 CREATE USER dbadmin=> CREATE USER User2; CREATE USER dbadmin=> CREATE USER User3; CREATE USER dbadmin=> CREATE SCHEMA s1; ROLLBACK 4213: Object "s1" already exists dbadmin=> GRANT USAGE on SCHEMA s1 TO User1, User2, User3; GRANT PRIVILEGE dbadmin=> CREATE ROLE reviewer; CREATE ROLE dbadmin=> GRANT CREATE ON SCHEMA s1 TO User1; GRANT PRIVILEGE dbadmin=> \c - user1 You are now connected as user "user1". dbadmin=> CREATE TABLE s1.t1(id int, sourceID VARCHAR(8)); CREATE TABLE dbadmin=> GRANT SELECT on s1.t1 to User2 WITH GRANT OPTION; GRANT PRIVILEGE #用户 2 通过 GRANT OPTION 给用户 3 授权 dbadmin=> \c - user2 You are now connected as user "user2". dbadmin=> GRANT SELECT on s1.t1 to User3 WITH GRANT OPTION; GRANT PRIVILEGE #用户 3 再把权限授权给角色 dbadmin=> \c - user3 You are now connected as user "user3". dbadmin=> GRANT SELECT on s1.t1 to reviewer; WARNING 5682: USAGE privilege on schema "s1" also needs to be granted to "reviewer" GRANT PRIVILEGE #用户 1 和用户 3 通过表 grants 都只能看到自己的权限 dbadmin=> SELECT grantor,privileges_description,object_schema,object_name,object_type,grantee FROM grants WHERE object_name = 's1' AND grantee ILIKE 'User%'; grantor | privileges_description | object_schema | object_name | object_type | grantee ---------+------------------------+---------------+-------------+-------------+--------- dbadmin | USAGE | | s1 | SCHEMA | User3 (1 row) dbadmin=> \c - user1 You are now connected as user "user1". dbadmin=> SELECT grantor,privileges_description,object_schema,object_name,object_type,grantee FROM grants WHERE object_name = 's1' AND grantee ILIKE 'User%'; grantor | privileges_description | object_schema | object_name | object_type | grantee ---------+------------------------+---------------+-------------+-------------+--------- dbadmin | USAGE, CREATE | | s1 | SCHEMA | User1 (1 row) 第 103 页 共 182 页 #超级用户可以看到所有权限 dbadmin=> \c - dbadmin Password: You are now connected as user "dbadmin". dbadmin=> SELECT grantor,privileges_description,object_schema,object_name,object_type,grantee FROM grants WHERE object_name = 's1' AND grantee ILIKE 'User%'; grantor | privileges_description | object_schema | object_name | object_type | grantee ---------+------------------------+---------------+-------------+-------------+--------- dbadmin | USAGE, CREATE | | s1 | SCHEMA | User1 dbadmin | USAGE | | s1 | SCHEMA | User2 dbadmin | USAGE | | s1 | SCHEMA | User3 (3 rows) dbadmin=> SELECT grantor,privileges_description,object_schema,object_name,object_type,grantee FROM grants WHERE object_name = 't1' AND grantee ILIKE 'User%'; grantor | privileges_description | object_schema | object_name | object_type | grantee ---------+-------------------------------------------------+---------------+-------------+-------------+--------- User1 | INSERT*, SELECT*, UPDATE*, DELETE*, REFERENCES* | s1 | t1 | TABLE | User1 User1 | SELECT* | s1 | t1 | TABLE | User2 User2 | SELECT* | s1 | t1 | TABLE | User3 (3 rows) #不使用 cascade 无法收回 user2 的权限 dbadmin=> \c - user1 You are now connected as user "user1". dbadmin=> REVOKE SELECT ON s1.t1 FROM User2 ; ROLLBACK 3052: Dependent privileges exist HINT: Use CASCADE to revoke them too dbadmin=> REVOKE grant option for select on s1.t1 FROM User2; ROLLBACK 3052: Dependent privileges exist HINT: Use CASCADE to revoke them too dbadmin=> \c - user2 You are now connected as user "user2". dbadmin=> select count(1) from s1.t1; count ------- 0 (1 row) #使用 cascade 收回 grant option 权限会一并收回通过 grant option 授予的权限 dbadmin=> \c - user1 You are now connected as user "user1". dbadmin=> REVOKE grant option for select on s1.t1 FROM User2 cascade; 第 104 页 共 182 页 REVOKE PRIVILEGE dbadmin=> SELECT grantor,privileges_description,object_schema,object_name,object_type,grantee FROM grants WHERE object_name = 't1' AND grantee ILIKE 'User%'; grantor | privileges_description | object_schema | object_name | object_type | grantee ---------+-------------------------------------------------+---------------+-------------+-------------+--------- User1 | INSERT*, SELECT*, UPDATE*, DELETE*, REFERENCES* | s1 | t1 | TABLE | User1 User1 | SELECT | s1 | t1 | TABLE | User2 (2 rows) #使用 cascade 收回权限也会一并收回通过 grant option 授予的权限 dbadmin=> \c - user1 You are now connected as user "user1". dbadmin=> REVOKE SELECT ON s1.t1 FROM User2 CASCADE; REVOKE PRIVILEGE dbadmin=> \c - dbadmin Password: You are now connected as user "dbadmin". dbadmin=> dbadmin=> SELECT grantor,privileges_description,object_schema,object_name,object_type,grantee FROM grants WHERE object_name = 't1' AND grantee ILIKE 'User%'; grantor | privileges_description | object_schema | object_name | object_type | grantee ---------+-------------------------------------------------+---------------+-------------+-------------+--------- User1 | INSERT*, SELECT*, UPDATE*, DELETE*, REFERENCES* | s1 | t1 | TABLE | User1 (1 row) 超级用户或者对象属主还可以通过 ALTER 命令修改对象的权限,主要是修改表的属主和序列的属主。对象 属主的转移只影响属主,不会将对象相关的权限一并转移。原来属主的授权会被删除,新属主可以操作当前表上 所有的权限。对象属主的转移会使得表上 IDENTITY/AUTO-INCREMENT 序列的属主一并转移,但是参考序列 的属主不发生变化。 修改属主的语法: ALTER TABLE [[db-name.]schema.]table-name OWNER TO new-owner name 需要注意的是表的权限和模式的权限是分开的,表属主的转移不会导致模式属主的转移。 因为 Projection 代表了表的物理定义,vertica 不需要单独的 Projection 属主,创建删除 Projection 的权限 也依赖于相应的表。 #修改对象属主后原属主授权的权限被删除 dbadmin=> \c - user1 You are now connected as user "user1". dbadmin=> grant select on s1.t1 to user3; 第 105 页 共 182 页 GRANT PRIVILEGE dbadmin=> dbadmin=> \c - dbadmin Password: You are now connected as user "dbadmin". dbadmin=> SELECT grantor,privileges_description,object_schema,object_name,object_type,grantee FROM grants WHERE object_name = 't1' AND grantee ILIKE 'User%'; grantor | privileges_description | object_schema | object_name | object_type | grantee ---------+-------------------------------------------------+---------------+-------------+-------------+--------- User1 | INSERT*, SELECT*, UPDATE*, DELETE*, REFERENCES* | s1 | t1 | TABLE | User1 User1 | SELECT | s1 | t1 | TABLE | User3 (2 rows) dbadmin=> alter table s1.t1 owner to user2; ALTER TABLE dbadmin=> SELECT grantor,privileges_description,object_schema,object_name,object_type,grantee FROM grants WHERE object_name = 't1' AND grantee ILIKE 'User%'; grantor | privileges_description | object_schema | object_name | object_type | grantee ---------+------------------------+---------------+-------------+-------------+--------- (0 rows) 修改序列的属主的语法: ALTER SEQUENCE sequence-name OWNER TO new-owner-name; 9.3.2 存储位置权限管理 通过授权可以运行非 DBA 用户读写指定的存储位置,这里的存储位置必须是 USER 类型的,所以需要首先 创建 USER 类型的存储位置。 对存储位置进行授权的命令: GRANT { READ | WRITE | ALL [ PRIVILEGES ] } ... ON LOCATION 'path' [, ON 'node' ] ... TO { username | role | PUBLIC } [, ...] ... ... [ WITH GRANT OPTION ] 参数 含义 READ | WRITE | ALL 允许指定读取、写入、读写指定存储位置, WRITE 权限同时允许导出 COPY 命 令的异常数据和拒绝数据。 ON LOCATION 'path' [, ON 'node' ] Path 指定存储位置的路径或者 mount 点,node 指定节点,如果忽略则指所操 第 106 页 共 182 页 作节点。 Username| role| PUBLIC 被授予权限的用户、角色、或者 public 角色 WITH GRANT OPTION 是否允许用户再对其它人授权 9.4 安全管理 Vertica 数据库有三种形式的安全操作:  客户端身份验证以阻止未授权访问数据库  连接加密以防止数据被截获以及服务器和客户端之间身份数据被截获  客户端身份验证通过用户和权限控制谁能访问和修改数据库 9.4.1 客户端身份验证 为了获取数据库连接,用户或者客户端应用程序需要一个有效的数据库用户账户,同时选择一种身份验证方 式,例如密码。根据连接的类型、客户端 IP 段、用户名不同可以选择不同的身份验证方式。 为了使得客户端和服务器之间的连接更加安全,可以配置数据库服务器和客户端之间进行 SSL 加密。 Vertica 通过使用 SSL 达到:帮助客户端认证服务器的身份,避免“中间人”攻击;加密源端和目标端传输的数 据,减少数据被截取的可能;验证客户端和服务器之间传输的数据是否经过修改。 当一个客户端(运行客户端的应用程序或客户端应用程序本身的用户)连接到 Vertica 数据库服务器,它提 供了获得 Vertica 数据库用户名。Vertica 限制数据库用户可以通过客户端认证连接数据库服务器,这个事一个当 数据库服务器建立请求客户端的身份和决定客户被授权连接到使用提供的凭据的过程。Vertica 提供几个客户端身 份验证方法。您可以配置 Vertica 要求只是一个用户名进行连接,但是你可能需要更多的安全认证,如在最低限 度的密码。 有两种类型的客户端认证:  LOCAL-本地认证的用户或应用程序试图从数据库运行在同一节点连接。  HOST-认证主机上的用户或应用程序正试图从一个节点具有不同的 IPv4 或 IPv6 地址 与数据库连接。IPv4,默认的掩码是 32 位;IPv6,默认的掩码是 128 位。 第 107 页 共 182 页 Vertica 采取以下步骤来验证用户的身份: 1、当用户或应用程序试图连接到一个惠普 Vertica 数据库,系统检查用户是否是 DBAdmin 用户。 DBAdmin 用户可以在任何时候访问数据库,除非他们是专门被认证的方法如拒绝。 2、非 DBAdmin 用户,数据库检查用户是否已被授予认证方法。如果是,数据库允许用户登录,如果他们 匹配该认证方法所需的参数。DBAdmin 用户可以授予的认证方法对用户或用户角色或撤销认证方法。 DBAdmin 用户还可以为一个没有认证的用户或角色分配一个默认的认证方法。 3、如果未授予用户认证方法,数据库会检查 DBAdmin 是否已经建立了一个默认身份验证方法。 4、如果有一个默认的认证方法,该数据库的用户进行身份验证,使用默认的方法。 5、如果没有默认的认证方法,则查看该数据库 DBAdmin 用户已定义的任何身份验证方法。如果没有,则 数据库没有认证信息。然而,如果一个密码存在,DBAdmin 用户可以登录。 6、如果有任何验证信息,Vertica 拒绝用户请求连接到数据库。DBAdmin 没有给予用户认证的方法也没有 定义一个默认 DBAdmin 所有用户的认证方法(“公共”)。 7、如果数据库中有无验证记录,vertica 使用隐式/隐式身份验证方式验证用户的密码。 Vertica 支持的客户端身份验证方法:  Trust authentication-信任认证:授权任何用户连接到服务器使用一个有效的用户名。  Reject authentication-拒绝认证:阻止连接并防止请求客户端访问数据库。  GSS authentication-GSS 认证:使用安全、单点登录、受信任的第三方,相互认证服 务连接到 vertica 数据库。GSS 认证使用 GSS-API 的标准和提供非 MIT Kerberos 实现兼容,如 Java 和 Windows 客户端。 注:客户端身份验证使用 Kerberos 5 在 Vertica 7 过时。GSS 认证代替 Kerberos 认证。  Hash authentication-哈希认证:发送加密的密码散列哈希认证通过 MD5 算法或更安 全的 SHA-512 的方法在网络上。服务器向客户端用 salt.。vertica 建议你使用哈希 验证代替密码验证。密码认证发送密码时,vertica 传送的明文。而哈希认证发送密 码安全。  LDAP authentication-LDAP 认证:工作如口令认证方法认证除了对 LDAP 轻量级目 录访问协议或 Active Directory 服务器客户端。  Ident authentication-身份认证:认证客户端对用户名的验证指定服务器。  TLS authentication-TLS(Transport Layer Security)认证:认证客户端使用一 个包含公钥的数字证书。传输层安全(TLS)的前身是安全套接字层(SSL)认证, 第 108 页 共 182 页 Authentication Method Local? Host? GSS No Yes Ident Yes Yes LDAP Yes Yes Hash Yes Yes Reject Yes Yes TLS No Yes Trust Yes Yes 9.4.2 管理客户端身份验证 DBAdmin 用户管理用户认证的记录,这些记录被存储在你的 Vertica 数据库。 重要提示:配置客户端认证,使得 DBAdmin 用户可以总是在本地访问数据库。DBAdmin 用户不需要认证。 如果认证发生问题,阻止所有用户的登录,DBAdmin 用户可以登录并解决问题。 DBAdmin 用户管理以下任务: Action How To Create an authentication record. 使用创建认证(CREATE AUTHENTICATION)语句定 义的认证记录你的数据库。惠普 Vertica 支持下列身份 验证方法:  Password  Trust  LDAP  GSS  Ident  Hash  Reject Set parameters for a given authentication method. 使用 ALTER 认证(ALTER AUTHENTICATION)语句 定义一个特定身份验证方法需要的参数。以下方法需要 的参数:  LDAP  Ident  GSS 第 109 页 共 182 页 Define an authentication method as the default method. 使用 ALTER 认证(ALTER AUTHENTICATION)语句 定义认证方法为默认认证。如果用户没有指定一个认证 方法,数据库试图验证使用默认的认证方法。 Grant an authentication method to a user. 使用授权认证(GRANT (Authentication))的语句指定 一个特定的认证方法给用户。如果你不指定一个认证方 法给用户,vertica 使用默认的认证方法。 你可以给一个用户多个身份验证方法。使用优先级确定 认证方法应首先尝试。 Revoke an authentication method assignment from a user. 使用撤销认证(REVOKE Authentication)语句从一个 用户删除一个身份验证方法。该方法已被撤销后, vertica 使用默认的身份验证方法对用户进行身份验 证。 Drop an authentication method from the database. 使用删除认证(DROP AUTHENTICATION)语句从数据 库删除一个身份验证方法。该方法已被删除后,vertica 使用默认的认证对任何用户的方法分配掉的方法。 作为 Vertica 7.1,您可以使用 VSQL 新的命令来管理客户端认证记录,但是不再能够使用 admintools 进 行客户端认证记录的管理了。 当你使用创建认证(CREATE AUTHENTICATION)语句创建认证记录时,指定以下信息: 认证方法名--定义的给 vertica 使用名称。 认证类型-身份验证或客户端试图连接数据库的身份验证类型:gss、ident、ldap、hash、reject、trust、 tls 访问方法:LOCAL、HOST、HOST NO TLS、HOST TLS 主机的 IP:访问数据库用户或应用的 IP 地址或者范围 下面的示例创建认证记录存储在 catalog 中。当你使用创建认证创建一个认证记录时,vertica 自动使它。 示例创建一个名叫 localpwd 身份验证方法来验证试图访问数据库用户的身份 => CREATE AUTHENTICATION localpwd METHOD 'hash' LOCAL; 此示例创建一个命名 v_ldap 的身份验证方法,使用 LDAP 在 TLS 协议验证用户登录与 IPv4 地址为 10.0.0.0/23 的主机的访问 => CREATE AUTHENTICATION v_ldap METHOD 'ldap' HOST TLS '10.0.0.0/23'; 此示例创建一个名为 v_kerberos 身份验证方法对用户进行身份验证,验证在网络中的任何主机连接 第 110 页 共 182 页 => CREATE AUTHENTICATION v_kerberos METHOD 'gss' HOST '0.0.0.0/0'; 此示例创建一个命名为 rejectnossl 认证方法,拒绝用户从任何 IP 地址是试图验证没有 SSL / TLS 的访问 => CREATE AUTHENTICATION RejectNoSSL METHOD 'reject' HOST NO TLS '0.0.0.0/0'; (IPv4) => CREATE AUTHENTICATION RejectNoSSL METHOD 'reject' HOST NO TLS '0.0.0.0/0'; (IPv6) 9.4.3 客户端身份验证优先级 如果一个用户被分配一个客户端身份验证方法,你不需要担心方法优先级。然而,如果多个身份验证方法被 分配给一个用户,vertica 决定哪一种身份验证最先使用。 客户端身份验证的优先顺序如下,从最高到最低:  用户指定的优先级为某个方法  最具体的 IP 地址比特定 IP 地址具有更高优先权的优先级,如 10.3.4.128/25 有比 10.3.0.0/24 高的优先级,而后者又有比 10.3.0.0/16 更高的优先级  Reject  GSS | LDAP | TLS | Ident  Hash  Trust 其它影响身份认证方法优先级的因素:  HOST 的优先级别 LOCAL 高  TLS 的优先级比 NO TLS 的高 如果未指定优先级,则默认为 0,设置方法如下: ALTER AUTHENTICATION ... PRIORITY ; 创建的身份认证方法存储在 catalog 中并自动默认启用,可以使用以下命令启用或者禁用身份认证方法: 禁用该身份认证方法: ALTER AUTHENTICATION v_kerberos DISABLE; 重新启用: ALTER AUTHENTICATION v_kerberos ENABLE; 第 111 页 共 182 页 9.4.5 授权和撤销身份认证 必须通过用户和角色授权用户使用所创建的身份认证方法,客户端或者应用程序在连接数据库时才能使用相 应的身份认证方法。可以通过授权给 public 角色身份认证方法以设置默认的身份认证方法。 授权 v_ldap 方法给 jsmith => GRANT AUTHENTICATION v_ldap TO jsmith; => REVOKE AUTHENTICATION v_ldap FROM jsmith; 授权 v_gss 给角色 DBprogrammer => CREATE ROLE DBprogrammer; => GRANT AUTHENTICATION v_gss to DBprogrammer; => REVOKE AUTHENTICATION v_gss FROM DBprogrammer; 授权 v_localpwd 给 public => GRANT AUTHENTICATION v_localpwd TO Public; => REVOKE AUTHENTICATION localpwd from Public; 9.4.6 修改身份认证方法 要修改客户端身份认证方法必须先连接到数据库,如下将涉及如何修改客户端身份认证方法。 禁用和重新启用 => ALTER AUTHENTICATION v_ldap DISABLE; => ALTER AUTHENTICATION v_ldap ENABLE; 改名: => ALTER AUTHENTICATION v_kerberos RENAME TO K5 ENABLE; 设置优先级 => ALTER AUTHENTICATION K5 PRIORITY 10; 修改参数 => CREATE AUTHENTICATION ident1 METHOD 'ident' LOCAL; => ALTER AUTHENTICATION ident1 SET system_users='root'; 下面的例子创建 LDAP 身份认证方法指定 LDAP 服务器的参数,vertica 连接到 LDAP 服务器进行身份验证, 如果认证成功,vertica 允许所有指定身份认证方法为 ldap1 的用户连接到数据库。 指定 LDAP 服务器 => CREATE AUTHENTICATION Ldap1 METHOD 'ldap' HOST '172.16.65.196'; => ALTER AUTHENTICATION Ldap1 SET host='ldap://172.16.65.177', binddn_prefix='cn=', binddn_suffix=',dc=qa_domain,dc=com'; 第 112 页 共 182 页 在下面这个例子中,指定 LDAP 的变量和 IP 地址。如果 vertica 没有足够的信息来给一个用户创建专有名称 (DN)的认证,你必须指定要使用的 LDAP 变量和搜索。 指定 LDAP 服务器 => CREATE AUTHENTICATION LDAP1 METHOD 'ldap' HOST '172.16.65.196'; => ALTER AUTHENTICATION Ldap1 SET host='ldap://172.16.65.177', basedn='dc=qa_domain,dc=com',binddn='cn=Manager,dc=qa_domain, dc=com',search_attribute='cn',bind_password='secret'; 修改 localpwd 认证方法为 hash => CREATE AUTHENTICATION localpwd METHOD 'trust' LOCAL; => ALTER AUTHENTICATION localpwd METHOD 'hash'; 删除某一身份认证方法 => DROP AUTHENTICATION md5_auth; 删除已授权用户的认证方法 => CREATE AUTHENTICATION localpwd METHOD 'password' LOCAL; => GRANT AUTHENTICATION localpwd TO jsmith; => DROP AUTHENTICATION localpwd CASCADE; 9.4.7 获得身份认证记录 V_catalog 模 式 下 的 系统 表 CLIENT_AUTH、CLIENT_AUTH_PARAMS、PASSWORD_AUDITOR、 USER_CLIENT_AUTH 有身份认证相关的记录信息。 要查看某一用户进出所使用的身份认证方法,可以查询 V_MONITOR 模 式 下 的 系统表 SESSIONS、 USER_SESSIONS 9.4.8 密码认证方法 最简单的认证客户端连接数据库的方法是使用密码,如果用户或者客户端有密码,则必须使用正确的密码才 能连接到 vertica 数据库。然而如果用户没有密码,vertica 没有其他方式的客户端身份认证,用户总是可以连接 到数据库的。 Vertica 口令用加密的格式存储以防止潜在的盗窃。然而该密码的传输是纯文本,因此有可能被“中间人攻击” 截获密码。 当你有任何未指定的认证方法,Vertica 使用密码认证所有有密码的用户的连接。如果你创建了身份验证方法, 哪怕是远程主机方式,密码认证就会被禁用的。在这种情况下,必须显式启用密码认证。下面的命令创建 第 113 页 共 182 页 local_pwd 认证方法和使其成为所有用户的默认方法。 => CREATE AUTHENTICATION local_pwd METHOD hash' LOCAL; => GRANT AUTHENTICATION local_pwd To Public; 生产系统认证策略: dbadmin=> create authentication hostpwd method 'hash' host '0.0.0.0/0'; CREATE AUTHENTICATION dbadmin=> create authentication localtrust method 'trust' local; CREATE AUTHENTICATION dbadmin=> grant authentication hostpwd to public; GRANT AUTHENTICATION dbadmin=> grant authentication localtrust to dbadmin; GRANT AUTHENTICATION 9.4.9 LDAP 认证方法 轻量级目录访问协议(LDAP)认证和密码认证类似。主要的区别是,LDAP 方法通过 LDAP 或活动目录服 务器认证用户对 vertica 数据库的访问。当所认证用户与 LDAP 或 Active Directory 服务器认证时使用 LDAP 认 证到数据库的连接。 10. 性能优化 10.1 资源管理器 - Resource Manager 当 SQL 查询发起之后会发生以下一系列的事件: 一、SQL 被解析生成执行计划,并发布到参与计算的节点 二、RM 参与,评估查询所需资源和系统资源当前的使用情况并决定使用哪种策略  如果查询的内存需求超过系统物理内存,查询被拒绝  如果查询所需的内存当前暂时无法满足,查询被加入等待队列直到,直到请求的资源得到满 足或者查询时间超时被拒绝  否则查询被执行 第 114 页 共 182 页 三、当参与节点允许其执行时查询开始执行。 查询开始执行之后 RM 可以通过资源池参数 RUNTIMEPRIORITY 和 RUNTIMEPRIORITYTHRESHOLD 控制其执行情况。而每个查询使用的资源和最大允许执行的查询都是由资源池的配置决定的。就每个节点来 说,vertica 不会为某一个查询保留或者锁住资源,但是对于多节点查询,如果某些节点处理队列状态,则其 它已获得资源的节点会保留其获得的资源,这种情况下 vertica 需要尽可能的避免死锁。 10.1.1 理解资源池的架构 Vertica 处理资源的方式是以一个或者多个资源池的形式,把系统资源分成一系列的子集并按照某种方式组合。 如下表所示 vertica 预先配置了一些内嵌的资源池: 内嵌资源池名称 设置 GENERAL 一个特殊的用来全方位应答所有未指定资源池的请求,所有其它资源池剩余的内存都会自 动配置到 general 池中,general 池的 MEMORYSIZE 参数是没有限制的,最小不能低于 1GB 且不小于系统内存的 25%。 MAXMEMORYSIZE 参数有特殊含义,如设置%值代表主机系统内存总量的百分比,默认情况是 95%,GENERAL.MAXMEMORYSIZE 管理所有的 RM RAM 可以被查询使用不管其设置为百分比 或者具体值。 任何用户定义的资源池可以从 general 池中“借”内存以满足请求需要的额外内存,直到 达到参数 MAXMEMORYSIZE 的设置,但是如果其定义 MEMORYSIZE 和 MAXMEMORYSIZE 相等的情 况下则不能从 general 中借内存,因为它被定义为了单独的资源池。如果同时有多个资源 池相 general 借内存,则按照每个资源池的优先级设定依次满足,在这种情况 下 GENERAL 会提供了一些弹性的即时偏差和自定义资源池正常使用相比。 SYSQUERY 保留资源以允许系统表查询以保障系统表访问不会由于资源争用而堵塞。 SYSDATA 为访问系统表产生的中间状态结果保留临时存储空间,如果该池设置过小,系统可能无法 访问大的系统表或者高并发访问系统表。 WOSDATA 数据加载到 WOS 之后一旦超过 WOS 限制会自动溢出到 ROS,WOS 溢出的阀值有参数 PLANNEDCONCURRENCY 控制。如该值设置为 4,即当加载数据到 WOS 的 1/4 时溢出数据到 ROS 中。 TM Tuple Mover (TM) 池,可以通过参数 MAXCONCURRENCY 控制可以并发运行的 TM 进程。 RECOVERY 用于其它节点发起的 recover 操作请求,参数 MAXCONCURRENCY 控制多少并发 recover 线程 可用,它同样也可以通过参数 PLANNEDCONCURRENCY 控制如何分配内存用于 recover 语句。 REFRESH 用于执行 PROJECTION_REFRESHES 操作的语句,由于它不支持并发线程,所以设置 MAXCONCURRENCY 是无效的。 DBD 用于控制 DB Designer 的内部处理语句的执行,由于 DB Designer 是资源密集型的操 作,所以 DBD 池 QUEUETIMEOUT=0s,当资源不够时 DBD 池会立即报错,而不进行队列等 第 115 页 共 182 页 待,vertica 不建议自行设置该池 JVM 用于控制执行用户自定义的 java 扩展程序,当一个用户自定义的程序启动 JVM 后,它会 为这些特定的任务从 JVM 池中拉出资源,但是系统并不为 JVM 保留内存,它最大可以扩 展到系统内存的 10%或者 2GB 中的小者。可以通过调整配置改变该池的大小,但是它跟 其它池不同支处是,session 结束之后资源才能释放。 #查询节点 1 的查询语句在队列中等待时间 dbadmin=> SELECT pool_name, queue_entry_timestamp, acquisition_timestamp, (acquisition_timestamp- queue_entry_timestamp) AS 'queue wait' FROM V_MONITOR.RESOURCE_ACQUISITIONS WHERE node_name ILIKE '%node0001' limit 10; pool_name | queue_entry_timestamp | acquisition_timestamp | queue wait -----------+-------------------------------+-------------------------------+----------------- general | 2014-08-22 15:40:27.077944+08 | 2014-08-22 15:40:27.07796+08 | 00:00:00.000016 general | 2014-08-22 15:40:16.965528+08 | 2014-08-22 15:40:16.965548+08 | 00:00:00.00002 general | 2014-08-22 15:40:15.343964+08 | 2014-08-22 15:40:15.343981+08 | 00:00:00.000017 general | 2014-08-22 15:40:06.86157+08 | 2014-08-22 15:40:06.861586+08 | 00:00:00.000016 general | 2014-08-22 15:39:56.768364+08 | 2014-08-22 15:39:56.768379+08 | 00:00:00.000015 general | 2014-08-22 15:39:43.886327+08 | 2014-08-22 15:39:43.886348+08 | 00:00:00.000021 general | 2014-08-22 15:39:33.767798+08 | 2014-08-22 15:39:33.767805+08 | 00:00:00.000007 general | 2014-08-22 15:39:29.259297+08 | 2014-08-22 15:39:29.259322+08 | 00:00:00.000025 general | 2014-08-22 15:26:45.310152+08 | 2014-08-22 15:26:45.310177+08 | 00:00:00.000025 general | 2014-08-22 15:26:42.884735+08 | 2014-08-22 15:26:42.884755+08 | 00:00:00.00002 (10 rows) #查询各个资源池的使用情况 dbadmin=> SELECT pool_name, memory_size_kb, memory_size_actual_kb, memory_inuse_kb, general_memory_borrowed_kb,running_query_count FROM V_MONITOR.RESOURCE_POOL_STATUS where node_name ilike '%node0001'; pool_name | memory_size_kb | memory_size_actual_kb | memory_inuse_kb | general_memory_borrowed_kb | running_query_count -----------+----------------+-----------------------+-----------------+----------------------------+--------------------- general | 2119592 | 2119592 | 8192 | 0 | 0 sysquery | 65536 | 65536 | 0 | 0 | 0 sysdata | 102400 | 102400 | 24576 | 0 | 0 wosdata | 0 | 0 | 0 | 8192 | 0 tm | 204800 | 204800 | 0 | 0 | 0 refresh | 0 | 0 | 0 | 0 | 0 recovery | 0 | 0 | 0 | 0 | 0 dbd | 0 | 0 | 0 | 0 | 0 jvm | 0 | 0 | 0 | 0 | 0 (9 rows) 10.1.2 管理资源池 为了控制不同的用户以不同的优先级等方式使用资源池,可以给用户设定 profile,它主要可以控制以下方面:  分配给用户的资源池 第 116 页 共 182 页  用户的会话最大可以使用的内存(MEMORYCAP)  用户的会话最大可以使用的临时存储空间(TEMPSPACECAP)  用户的会话最长运行的执行时间(RUNTIMECAP) 所有这些策略都可以通过创建用户(create user)时指定或者通过 alter user 修改,对于用户资源使用策略 的控制可以通过直接指定方式,或者指定资源池的方式。 #修改用户资源限制 dbadmin=> alter user lizy MEMORYCAP '750M' RUNTIMECAP '10 minutes'; ALTER USER dbadmin=> 资 源 池 的 参 数 MEMORYSIZE 和 PLANNEDCONCURRENCY 控制分配给查询的内存,系统表 V_MONITOR.RESOURCE_POOL_STATUS 的字段 query_budget_kb 显示了实际分配给查询的内存情况,一般 情况下不需要对查询相关的资源池进行优化,如确有必要时按以下简单公式计算:如果 MEMORYSIZE 设置为 0, 它的所有内存都从 general 池中借取,并通过参数 MEMORYSIZE 和 PLANNEDCONCURRENCY 控制每个查 询的内存分配;如果另外一个资源池设定了 MEMORYSIZE 参数,而且该资源池是独立的资源池,其不能从 general 池中借内存,查询所能用到的内存有该资源池的参数 PLANNEDCONCURRENCY 确定;另外资源池设 定了 MEMORYSIZE 参数,单不是独立资源池,那么它同样有 MEMORYSIZE 和 PLANNEDCONCURRENCY 控制内存使用大小。 RM(资源管理器)可以控制分配给查询的资源,以及查询什么时候运行、什么时候等待,对于已经运行的查 询 RM 仍然可以通过设置资源池运行状态优先级或者设置查询语句运行状态优先级来调整其资源的分配。 首先,设置资源池的运行状态优先级方式,对于每个资源池都可以管理已经运行的查询的资源分配情况,可 以指定资源池的运行状态优先级为 HIGH、MEDIUM、LOW 中的一个。该设定决定了分配给查询的运行状态的 资源如 CPU、IO 等,如设定运行状态优先级为 HIGH 的查询比 MEDIUM 和 LOW 能获得更多的运行时资源。 运行状态资源池可以帮助弹性的管理资源,一般来说总是希望速度快的查询使用高优先级,其它的查询使用 中或者低优先级。RM 有一个运行状态优先级的控制阀值,所有查询开始都是高优先级,当查询超出控制阀值未 完成时,自动分配其它运行状态优先级。 参数 描述 RUNTIMEPRIORITY  HIGH  MEDIUM  LOW 运行状态优先级为 HIGH 的查询比 MEDIUM 和 LOW 能获得更多的运行 时资源 RUNTIMEPRIORITYTHRESHOLD 指定一个以秒为单位的时间限制,查询如果不能完成则被 RM 分配运行状 第 117 页 共 182 页 态优先级。 其次通过函数 CHANGE_CURRENT_STATEMENT_RUNTIME_PRIORITY 可以修改查询的运行状态优先级,该函数需要 指定 transaction id 和运行状态优先级,但是不能对未开始的查询修改优先级。 只有数据库管理员才能修改任何查询的运行状态优先级到任何级别,用户只能修改自己运行查询的运行状态 优先级,且不能超过自身分配的资源池的级别或者限制。 系统表 V_CATALOG.RESOURCE_POOL_DEFAULTS 可以查到所有内建资源池的默认优先级,如果需要 改回默认优先级,设定 RUNTIMEPRIORITY 为 default 即可。 #当前进程的 transaction id dbadmin=> SELECT transaction_id, runtime_priority, transaction_description from SESSIONS; transaction_id | runtime_priority | transaction_description -------------------+------------------+------------------------------------------------------------------------------------------------ 49539595901411595 | | user dbadmin (SELECT transaction_id, runtime_priority, transaction_description from SESSIONS;) -1 | | (2 rows) #只能分配当前运行查询的优先级 dbadmin=> SELECT CHANGE_CURRENT_STATEMENT_RUNTIME_PRIORITY(49539595901411595, 'low'); ERROR 5703: Couldn't find the specified task, or the Resource Manager has not recieved the request HINT: Some SQL statements need to take certain locks before registering request with the Resource Manager ERROR 2932: Couldn't find the specified task #修改资源池的默认优先级 dbadmin=> ALTER RESOURCE POOL sysquery RUNTIMEPRIORITY DEFAULT; ALTER RESOURCE POOL 10.1.3 资源负载管理最佳实践 不同的查询、数据量、硬件配置、并发度对系统参数配置要求都有所不同,vertica 建议根据实际情况优化自 己的资源池使用情况。 当并发的运行多个查询时,所有查询共享 CPU、IO、网络带宽等资源,因此每一个查询执行时间可能比单独 运行的时间要长。在一个高效的、具有良好扩展性的系统,如果一个查询使用所有可用的资源执行时间为 X,那 么两个这样的查询执行时间应该为 2X。如果执行时间>2X,那么系统不是线性扩展的;如果执行时间<2X,那么 说明单个该查询浪费了系统资源。并发查询都可以获得必要的系统资源,执行时间主要局限于 CPU 速度,这种情 形是具有良好扩展性的表现,当然如果出现查询不能获得必需的资源的情况说明系统出现了瓶颈,想要再提高并 发必需增加系统资源。 实践中,我们 vertica 应该达到基本线性扩展,适当的并发且线性扩展,但并没有达到系统瓶颈是我们说期 望的。在表已经分段的集群中,增加节点基本可以实现线性扩展。 以下是和资源池相关的参数,默认的参数配置是用于平衡的、高吞吐的系统,可以通过调整以下参数优化相 第 118 页 共 182 页 应的负载问题,这些参数主要是基于 CPU、内存、IO 子系统、网络: 参数 配置 MEMORYSIZE 对于 GENERAL 池可以忽略 对于其它池默认 0%,指可以从 GENERAL 借的内存大小,设置时考虑以下情况: 1、 对于该池中特定的查询给予额外的内存,该内存不能被其它进程所用,那么是 该池没有查询的情况下; 2、 和参数 PLANNEDCONCURRENCY 配合使用以优化指定查询的内存使用,这是专家级 别的使用。 MAXMEMORYSIZE 对于 GENERAL 池可以忽略 对于其它池用于限制该池的大小或者可以从 GENERAL 池借内存的上限,它提供了一 种机制,用以加强对某些类别的工作负载的内存使用情况的硬限制。如加载数据的 进程不能使用超过 4GB 的可用内存。 EXECUTIONPARALLELISM 此参数用于限制在这个资源池中处理任何单一查询的线程的并发数量。减小该值能 够提升该资源池中小查询的吞吐量,尤其是当查询并发执行时。如果选择 AUTO 会 由系统来选择,如果选择手动设置,请输入 1 到 CPU core 的数量。 PRIORITY 此参数用于排序 GENERAL 池的资源请求,无论是直接发起到 GENERAL 池的请求还是 从 GENERAL 池借内存的请求。 内部池(SYSQUERY, RECOVERY, TM)优先级的范围是 110,DBA 创建的资源池的范围 是 100,内部池的优先级要总是比 DBA 创建的优先级高。 资源池的优先级是相对的,拥有高优先级的资源池和拥有低优先级的资源池具有相 同的增量资源的访问。 对于单独资源池优先级没有意义,因为它不向 GENERAL 池借内存。 RUNTIMEPRIORITY 此参数用于设置查询运行状态的优先级,任何超过参数 RUNTIMEPRIORITYTHRESHOLD 指定的限制未完成的查询都被赋予该参数指定的优先级。 1、 如果你期望达到短查询获得高优先级的效果,设置 RUNTIMEPRIORITY 为 MEDIUM 或者 LOW 优先级,RUNTIMEPRIORITYTHRESHOLD 设置为一个小的数 字以适应你的查询。 2、 如果你希望所有查询都有相同的优先级,那么可以设置 RUNTIMEPRIORITY 为 HIGH、MEDIUM、LOW,RUNTIMEPRIORITYTHRESHOLD 设置 0。 RUNTIMEPRIORITYTHRESHOLD 此参数用于指定查询总是用于高优先级执行的时间,默认值为 2(s),设置为 0 即关掉该特性。 QUEUETIMEOUT 此参数用于改变资源池超时时间(默认 5m) 它可以用于定制不同负载的超时间隔,比如对于长的批量操作,得到结果比响应时 间重要,所以可能提高该值或者不限制;对于交互式的应用,降低该值或者设置为 0,让无法立即获得资源的查询马上报错,而不进入等待队列。 第 119 页 共 182 页 需要注意:提高该值会增加等待队列,但是并不一定增加系统吞吐量 PLANNEDCONCURRENCY 此参数用于设定资源池的并行度 当设置为 AUTO 时,由 vertica 来评估该参数值,它会选择 CPU core 数量、 RAM/2GB 中的较小者,但是最小值不低于 4。 Vertica 建议根据一段时间系统性能的评估调整该参数。 对于 TM 池来说,参数 PLANNEDCONCURRENCY 的设置要和 CPU、内存、IO 子系统相 适应的。对于某一 IO 子系统,提高该值可能会造成系统的 IO 瓶颈。所以需要根据 对 IO 子系统的队列长度、多队列、写延迟的监控,及时调整设置以保障不会造成 IO 系统的瓶颈。另外同时需要考虑,分区数据文件;调整 block-size 优化 IO 系统 如 RAID5 或者 RAID 10。 说明: 考虑在每个查询的最大资源量和一定时间内并发查询的数量取一个平衡。 结合参数 MEMORYSIZE 一起使用控制查询的内存使用量 对于节点的 CPU core 不一致的集群来说,设置 AUTO 以适应不同的节点,分布式 查询运行像最小有效计划的并发。 MAXCONCURRENCY 此参数用于控制资源池上的最大并发数,包括 GENERAL 池。 也可以从连接层来控制最大的并发连接数,有参数 MaxClientSessions 控制。 RUNTIMECAP 此参数用于控制失控的查询,它指定查询所能执行的最大时间,设置该参数为一个 时间间隔,如'1 minute' or '100 seconds',但是最大不能超过一年。 如果用户或者 session 也有 RUNTIMECAP 限制,则取其中最小的一个。 SINGLEINITIATOR 该参数已过时,用于向后兼容,不必修改默认值 CPUAFFINITYSET 此参数用于指定资源池锁定的 CPU 数量,它要保持在集群间一致,可以通过命 令:lscpu | grep "^CPU(s)"查看系统 CPU 数。 CPUAFFINITYMODE 此参数用于控制资源池中独占模式或共享模式锁定的有参数 CPUAFFINITYSET 指定 的 CPU 数量。  场景 1-数据加载:每天晚上都有批量加载操作,或者白天偶尔也会有,数据加载期间查询可以接受资源 分配的减少,但是其他时间资源对查询全部可用。  解决方案:创建一个单独的用于数据加载的资源池,其优先级高于 GENERAL 池,这样当数据加载操作发 起之后,会从 GENERAL 池借内存,而其它时间内存对所有查询可用。 如果考虑使用 WOS,那么设置 PLANNEDCONCURRENCY 参数以便自动溢出数据到 ROS。 #创建加载数据资源池 dbadmin=> CREATE RESOURCE POOL load_pool PRIORITY 10; 第 120 页 共 182 页 CREATE RESOURCE POOL #调整 WOS 并发度 dbadmin=> ALTER RESOURCE POOL WOSDATA PLANNEDCONCURRENCY 6; ALTER RESOURCE POOL #修改用户默认的资源池 dbadmin=> ALTER USER lizy RESOURCE POOL load_pool; ALTER USER  场景 2-CEO 查询:CEO 每周一早上 9 点需要取一个报表,务必保证其正常运行。  解决方案:通过以下步骤来决定分配多少内存给 CEO 每周运行的查询语句。 #1 使用 profile 来检查 CEO 查询语句的内存使用量 dbadmin=> PROFILE select dbadmin-> basst_sel_ad, dbadmin-> case when count(usr_id)>20000 then 'Grd1' dbadmin-> when count(usr_id)>10000 and count(usr_id)<=20000 then 'Grd2' dbadmin-> when count(usr_id)>5000 and count(usr_id)<=10000 then 'Grd3' dbadmin-> when count(usr_id)>1000 and count(usr_id)<=5000 then 'Grd4' dbadmin-> when count(usr_id)>0 and count(usr_id)<=1000 then 'Grd5' dbadmin-> end basst_Grd dbadmin-> from dbadmin-> (select t.basst_sel_ad,t.usr_id from ods_ucm.cell_11 t dbadmin(> group by t.basst_sel_ad,t.usr_id) t dbadmin-> group by basst_sel_ad limit 10; NOTICE 4788: Statement is being profiled HINT: Select * from v_monitor.execution_engine_profiles where transaction_id=45035996275146849 and statement_id=1; NOTICE 3557: Initiator memory for query: [on pool general: 2303976 KB, minimum: 2303976 KB] basst_sel_ad | basst_Grd --------------+----------- - | Grd5 -1 | Grd5 0 | Grd4 00-00 | Grd5 00-80 | Grd5 0000 | Grd4 00000 | Grd1 00001 | Grd4 00002 | Grd5 00003 | Grd5 (10 rows) #2 上面结果提示了 CEO 查询的内存需要量,根据该值创建资源池并且指定 MEMORYSIZE 大于上述值 dbadmin=> CREATE RESOURCE POOL ceo_pool MEMORYSIZE '2500M' PRIORITY 10; CREATE RESOURCE POOL 第 121 页 共 182 页 dbadmin=> ALTER USER lizy RESOURCE POOL ceo_pool; ALTER USER  场景 3-阻止大查询:某一业务分析员在业务时间经常执行大的查询,有时会消耗整个机器的资源,希望 限制其查询使用的内存不超过 100M,执行时间不超过 2 小时。  解决方案:使用用户 profile 来实现该目标,指定 MEMORYCAP 为 100M,RUNTIMECAP 为 2 小时。 如果有一类用户都会。 => ALTER USER analyst_user MEMORYCAP '100M' RUNTIMECAP '2 hours';  场景 4-限制低效查询:有一批 SQL 开发经验不足的人,往往会写一些低效的大查询,影响系统性能甚 至可能会造成系统崩溃。现在需要限制这类用户的资源使用情况。  解决方案:最简单的方案就是创建一个单独的资源池分配给这些用户使用,由于它的 MEMORYSIZE 和 MAXMEMORYSIZE 大小一样,所以不能从 GENERAL 池借内存。另外增加 RUNTIMECAP 的限制。 其它的解决方案还可以是限制单个用户的内存使用,提升开发人员 SQL 技能。 #创建 standalone 资源池,然后分配给用户 dbadmin=> CREATE RESOURCE POOL adhoc_pool MEMORYSIZE '200M' MAXMEMORYSIZE '200M' PRIORITY 0 QUEUETIMEOUT 300 PLANNEDCONCURRENCY 4; CREATE RESOURCE POOL Time: First fetch (0 rows): 13.812 ms. All rows formatted: 13.828 ms  场景 5-应用并发硬性限制:如何实现对应用系统并发的硬性限制?  解决方案:最简单的方案是创建一个自定义的资源池,设定 MAXCONCURRENCY 的限制。 #创建限制并发的资源池 => CREATE RESOURCE POOL billing_pool MAXCONCURRENCY 3 QUEUETIMEOUT 2; => CREATE USER bill1_user RESOURCE POOL billing_pool; => CREATE USER bill2_user RESOURCE POOL billing_pool; => CREATE USER bill3_user RESOURCE POOL billing_pool; => CREATE USER bill4_user RESOURCE POOL billing_pool; => SELECT pool_name, thread_count, open_file_handle_count, memory_inuse_kb FROM RESOURCE_ACQUISITIONS WHERE pool_name = 'billing_pool'; pool_name | thread_count | open_file_handle_count | memory_inuse_kb --------------+--------------+------------------------+----------------- 第 122 页 共 182 页 billing_pool | 4 | 5 | 132870 billing_pool | 4 | 5 | 132870 billing_pool | 4 | 5 | 132870 (3 rows)  场景 6-混合应用:考虑一套系统同时有交互式应用和批量操作,当批量操作运行之后,交互式应用响应 缓慢,用户抱怨很大,如何处理?  解决方案:最基本的原则是把不同应用分成不同的用户,每个用户使用自己的资源池,如果可实现的话 这可以作为应用设计的最佳实践。 #方法 1、为 web 应用创建一个专用的资源池 CREATE RESOURCE POOL web_pool MEMORYSIZE '250M' MAXMEMORYSIZE NONE PRIORITY 10 MAXCONCURRENCY 5 PLANNEDCONCURRENCY 1 #方法 2、为批量操作创建一个独立的资源池 CREATE RESOURCE POOL batch_pool MEMORYSIZE '4G' MAXMEMORYSIZE '4G' MAXCONCURRENCY 10  场景 7-为不同用户查询分级:考虑给不同部门的用户查询设置不同的优先级。  解决方案:和混合应用场景类似,不限制资源使用,但是设置不同的优先级。创建两个资源池, MEMORYSIZE=0%但是 PRIORITY 不同。它们都可以向 general 池借内存,只是不同级别的获得响应 不同。 => CREATE RESOURCE POOL dept1_pool PRIORITY 5; => CREATE RESOURCE POOL dept2_pool PRIORITY 8; #如果以上情况老是出现一个部门的请求无法满足,可以考虑 => ALTER RESOURCE POOL dept1_pool MEMORYSIZE '100M'; => ALTER RESOURCE POOL dept2_pool MEMORYSIZE '150M';  场景 8-持续的数据加载和查询:数据加载操作持续进行,同时还有查询操作,如何保证性能符合预期。  解决方案:首先决定平均的加载数据并发度;为 WOS 池设置并发度 PLANNEDCONCURRENCY,同 时设置 MEMORYSIZE 以便数据适时溢出到 ROS;运行一段时间的数据加载验证性能是否符合预期; 如果有多种查询混合参考场景 6;运行查询并观察性能表现。 第 123 页 共 182 页  场景 9-为短查询设置运行优先级:继续场景 4,考虑如果是短查询,则需要保证其尽快完成。  解决方案:设置运行状态优先级为 MEDIUM 或 LOW,同时设置 RUNTIMEPRIORITYTHRESHOLD 参数。 => ALTER RESOURCE POOL ad_hoc_pool RUNTIMEPRIORITY medium RUNTIMEPRIORITYTHRESHOLD 5;  场景 10-为长查询设置低运行优先级:希望除了超过 1 个小时的长查询运行低优先级,其它查询都尽量 运行高优先级。  解决方案:设置运行状态优先级为 LOW,同时设置 RUNTIMEPRIORITYTHRESHOLD=3600 参数。 => ALTER RESOURCE POOL ad_hoc_pool RUNTIMEPRIORITY low RUNTIMEPRIORITYTHRESHOLD 3600; 第 124 页 共 182 页 10.2 统计信息收集 Vertica 的 CBO 优化器依赖数据的典型统计信息去生成查询的最终执行计划,优化器能够根据最新的统计信 息决定选择以下优化方式:  多个符合条件的 projection 去回复查询  关联的最佳顺序  涉及诸如 hash join/merge join 或者 hash/group by 等算法的执行计划  涉及诸如 re-segmention/broadcast 等算法的执行计划 因此,没有合理的统计信息,优化器往往选择不太优化的 projection 或者关联顺序。为了能够更好的理解 vertica 是如何收集统计信息的,请考虑下面的场景:有一张大表,频繁的(如每小时/每天)加载含时间戳的数 据,然后查询最近加载的行数。 优化器决定执行计划:如加载了第一到第十五天的数据,然后执行 ANALYZE_STATISTICS()函数,下次需 要通过时间戳查询昨天的数据时,优化器可以选择一个基于时间戳优化的执行计划。如果此时第二天加载第十六 天的数据,执行同一个查询,但是此时不执行 ANALYZE_STATISTICS(),优化器可能会推断微词的结果只有一 行数据,因为数据范围和柱状图范围不同,数据的统计信息过旧了。当出现统计信息过旧的情况后,vertica 优化 器会使用其它条件如主外键约束查询数据。 解决方案:每次加载数据之后执行 ANALYZE_STATISTICS()收集统计信息,对本例中的情形也可以使用 EXPLAIN plan 查询统计信息的情况,如果出现统计信息过旧 EXPLAIN plan 会在返回中包含一个状态信息。 Vertica 统计信息模型中主要考虑以下几个方面:  表的行数  每列的 distinct 值(cardinality)  每列的最大最小值  每列值得等高柱状图  列的磁盘空间使用情况 第 125 页 共 182 页 需要说明的是查询优化器和 database designer 使用的是同一份统计信息,当他们相关联的时候优化器会直 接使用 DB designer 创建的 projection。 10.2.1 如何收集统计信息 统计信息收集操作是一个集群级的通过历史查询(historical query)无锁的访问数据,经过计算之后存储在 catalog 中并且同步到所有节点。往存储的操作需要一个类似 DDL 锁的简单的独占锁,实际上这些操作过程中要 求提交当前的事务。 Vertica 有三种方式可以手动收集统计信息:  ANALYZE ROW COUNT:它是一种轻量级的自动的默认每 60 秒收集一次 projection 行数以 及加载数据的最小化统计信息和行数。默认的收集间隔可以有参数 AnalyzeRowCountInterval 控制,也可以执行 DO_TM_TASK ('analyze_row_count')过程进行手动收集。  ANALYZE_STATISTICS:它收集数据库、表或者列上完整的统计信息,有以下特点:  允许对表进行基于列的统计信息分析,以提升性能。  进行快速采样,加速包含大量列的小表的分析  包含 WOS 中的数据  重组删除数据,而不是忽略删除标记  允许你通过 CTRL-C 或者 INTERRUPT_STATEMENT()取消正在执行的收集过程  记录最近的统计信息收集时间,以便后续收集过程能够得到优化  ANALYZE_HISTOGRAM:事实上 ANALYZE_STATISTICS()是 ANALYZE_HISTOGRAM 别名,它们主要的不同之处是 ANALYZE_HISTOGRAM 允许指定从磁盘读取数据的百分比,由 此可以获得更多的采样精度和速度的控制。默认的采样百分比是 10%,可以指定 1~100%的值, 另外也可以指定 smaller 或者 larger 百分比,指定了百分比参数之后统计信息的精度和收集速 度都会受到影响。 不管采样百分比是多少,ANALYZE_HISTOGRAM 最多使用每列 128K 行的数据,采样 128K 并创建一个精确表现被采样数据的样本,即便是被采样列行数超过 1000000 行。通过随机的读取 每列被采样的数据创建一个柱状图,如果某一列的数据对应采样百分比的行数小于 128K,则至少 选取 128K 的记录,所以足够的数据样本是从磁盘读取。如果一列行数小于 128K,则读取所有数 据。 Column Size Percent Read from disk Sampled rows <128K rows 20 All rows Entire column 400,000 rows 10 128,000 128K rows 4,000,000 rows 10 400,000 128K rows 第 126 页 共 182 页 需要说明的是:如果被采样列是 Projection 中排序的第一列,则 ANALYZE_HISTOGRAM 会选 择读取所有数据以避免造成倾斜的采样数据 #分析表统计信息 dbadmin=> SELECT ANALYZE_STATISTICS('lizy.cell_11'); ANALYZE_STATISTICS -------------------- 0 (1 row) dbadmin=> SELECT ANALYZE_STATISTICS('ods_ucm.cell_11'); ANALYZE_STATISTICS -------------------- 0 (1 row) #虽然第一次收集使用 ANALYZE_STATISTICS 第二次收集使用了 ANALYZE_HISTOGRAM,但是收集速度仍然加快很多 dbadmin=> SELECT ANALYZE_HISTOGRAM('ods_ucm.cell_11'); ANALYZE_HISTOGRAM ------------------- 0 (1 row) #指定采样百分比 dbadmin=> SELECT ANALYZE_HISTOGRAM('lizy.cell_22', 100); ANALYZE_HISTOGRAM ------------------- 0 (1 row) Vertica 在加载数据过程中并不计算增量统计信息或者完整的统计信息,对于超过 250K 的大表,柱状图信 息包含最大、最小值、键值分布是基于其中的采样集计算而来。默认的采样集大小大约为 2^17(131702)或者 填满 1GB 内存的行数中的较小者。如果需要删除统计信息,执行 DROP_STATISTICS()实现。 dbadmin=> select a.STATISTICS_TYPE,a.statistics_updated_timestamp,a.table_column_name from PROJECTION_COLUMNS a where a.table_name in ('test_location') ; STATISTICS_TYPE | statistics_updated_timestamp | table_column_name -----------------+-------------------------------+------------------- FULL | 2014-08-12 17:46:39.085859+08 | usr_id FULL | 2014-08-12 09:26:18.602151+08 | year_month FULL | 2014-08-12 09:26:18.602162+08 | hour_nbr FULL | 2014-08-12 09:26:18.60217+08 | area_cty FULL | 2014-08-12 17:46:39.085899+08 | basst_sel_ad FULL | 2014-08-12 09:26:18.602183+08 | basst_hour FULL | 2014-08-12 09:26:18.60219+08 | pvc_cd FULL | 2014-08-12 17:46:39.085956+08 | usr_id FULL | 2014-08-12 09:26:18.602151+08 | year_month FULL | 2014-08-12 09:26:18.602162+08 | hour_nbr FULL | 2014-08-12 09:26:18.60217+08 | area_cty FULL | 2014-08-12 17:46:39.085997+08 | basst_sel_ad FULL | 2014-08-12 09:26:18.602183+08 | basst_hour 第 127 页 共 182 页 FULL | 2014-08-12 09:26:18.60219+08 | pvc_cd (14 rows) dbadmin=> select DROP_STATISTICS('vertica.test_location'); DROP_STATISTICS ----------------- 0 (1 row) #为什么 rowcount 统计信息 drop 不掉? dbadmin=> select a.STATISTICS_TYPE,a.statistics_updated_timestamp,a.table_column_name from PROJECTION_COLUMNS a where a.table_name in ('test_location') ; STATISTICS_TYPE | statistics_updated_timestamp | table_column_name -----------------+-------------------------------+------------------- ROWCOUNT | 2014-08-20 11:25:31.054149+08 | usr_id ROWCOUNT | 2014-08-20 11:25:31.054188+08 | year_month ROWCOUNT | 2014-08-20 11:25:31.054201+08 | hour_nbr ROWCOUNT | 2014-08-20 11:25:31.054211+08 | area_cty ROWCOUNT | 2014-08-20 11:25:31.05422+08 | basst_sel_ad ROWCOUNT | 2014-08-20 11:25:31.05423+08 | basst_hour ROWCOUNT | 2014-08-20 11:25:31.05424+08 | pvc_cd ROWCOUNT | 2014-08-20 11:25:31.054253+08 | usr_id ROWCOUNT | 2014-08-20 11:25:31.054262+08 | year_month ROWCOUNT | 2014-08-20 11:25:31.054271+08 | hour_nbr ROWCOUNT | 2014-08-20 11:25:31.05428+08 | area_cty ROWCOUNT | 2014-08-20 11:25:31.054289+08 | basst_sel_ad ROWCOUNT | 2014-08-20 11:25:31.054298+08 | basst_hour ROWCOUNT | 2014-08-20 11:25:31.054307+08 | pvc_cd (14 rows) 10.2.2 统计信息收集最佳实践 多数情况下没有必要要求统计信息非常精确的优化器才能生成好的执行计划,rowcount 统计信息已经包含 选择最优执行计划所必须的信息,所以只收集 rowcount 统计信息即可。 对表执行 ANALYZE_STATISTICS 往往很可能是耗时较久的操作,vertica 建议以下情形可以考虑使用其进 行统计信息收集:  表第一次被加载数据  新表进行了数据加载操作,Projection 被创建和刷新,在此之前 Projection 没有统计信息  表上 50%的行发生了变化  表上的列最大、最小值变化了 50%  新插入了主键值并且存储参考完整性约束,此时主键和外键都应该重新分析  相关表的大小,比表被加入时,发生重大变化 第 128 页 共 182 页  数据分布上出现显着的偏差,这就需要重新计算直方图  数据库有停机窗口可用 对于 vertica 数据库尤其是大表来说,收集重要列的统计信息,更有实际意义,并且能够节省时间。在列每 次进行了 alter table add 或者 modify 之后,收集列的统计信息是一个比较好的做法,如果收集统计信息之后查 询仍然很慢,可以通过 Database Designer 创建增量的设计以优化查询效率。 当系统运行良好之后,可以对统计信息进行备份,在个别场景像系统升级可能会造成统计信息改变影响执行 计划的情况,可以把旧的统计信息导回以恢复执行计划。 10.2.3 导出 profile 数据 工具 collect_diag_dump.sh 导出运行状态的数据库的系统表、 design 、 执 行 计 划 到 一 个 类 似./diag_dump_.tar.gz 命名的文件中。 参数 描述 -U User name, typically the database administrator account, dbadmin. -w Database password. -c Includes a compression analysis, resulting in a longer script execution time [dbadmin@V2 ~]$ /opt/vertica/scripts/collect_diag_dump.sh -U dbadmin -w 123456 -c Exporting profiling data........ Done Exporting system tables.......................................................... Done Exporting catalog and design.. Done Computing compression Done Forming archive file Done Diagnostics dump available at ./diag_dump_20140820173854.tar.gz 10.3 理解执行计划 Vertica 使用基于 CBO(cost-based query optimizer)的优化器管理执行计划,同一条查询语句可能有很 多不同的执行计划可以达到相同的目的,vertica 评估一个代价最低的执行计划。代价是指对资源使用的评估,包 括数据分布、CPU、内存、磁盘、网络、数据分段等,它依赖于统计信息,但是需要说明的是优化器不跨查询评 估代价,如查询 1 的代价比查询 2 的代价高并不一定得出查询 2 执行时间更短,或者短多少。 除了如 10.2 章所提到的统计信息模型中的主要方面以外,优化前还会考虑以下因素来优化某一查询语句:  使用最少 IO、CPU、内存、网络带宽的访问路径  多个适合的 Projection 返回给查询 第 129 页 共 182 页  不同的关联方式(hash join、merge join、hash group by、sort group by)  不同的关联顺序  查询谓词  数据在集群间的再分布方式(broadcast and re-segmentation) 10.3.1 如何获取执行计划 Vertica 有三种方式可以获取执行计划:  使用 EXPLAIN 方式  查询系统表 QUERY_PLAN_PROFILING  使用 Management Console Explain 选项 #EXPLAIN 方式查看执行计划 dbadmin=> explain select * from lizy.cell_11; QUERY PLAN -------------------------------------------------------------------------------------------------------------------- ------------------------------ QUERY PLAN DESCRIPTION: ------------------------------ explain select * from lizy.cell_11; Access Path: +-STORAGE ACCESS for cell_11 [Cost: 204K, Rows: 20M] (PATH ID: 1) | Projection: lizy.cell_11_DBD_4_seg_cell_11_b1 | Materialize: cell_11.year_month, cell_11.pvc_cd, cell_11.hour_nbr, cell_11.basst_hour, cell_11.area_cty, cell_11.usr_id, cell_11.basst_sel_ad | Execute on: v_vertica_node0003 +-STORAGE ACCESS for cell_11 (REPLACEMENT FOR DOWN NODE) [Cost: 102K, Rows: 20M] | Projection: lizy.cell_11_DBD_4_seg_cell_11_b0 | Materialize: cell_11.year_month, cell_11.pvc_cd, cell_11.hour_nbr, cell_11.basst_hour, cell_11.area_cty, cell_11.usr_id, cell_11.basst_sel_ad | Execute on: v_vertica_node0001, v_vertica_node0003 ------------------------------ ----------------------------------------------- PLAN: BASE QUERY PLAN (GraphViz Format) ----------------------------------------------- digraph G { graph [rankdir=BT, label = "BASE QUERY PLAN\nQuery: explain select * from lizy.cell_11;\n\nAll Nodes Vector: \n\n node[0]=v_vertica_node0001 (initiator) Up\n node[1]=v_vertica_node0003 (executor) Up\n node[2]=v_vertica_node0002 (executor) Down\n", labelloc=t, labeljust=l ordering=out] 0[label = "Root \nOutBlk=[UncTuple(7)]", color = "green", shape = "house"]; 1[label = "NewEENode \nOutBlk=[UncTuple(7)]", color = "green", shape = "box"]; 2[label = "ExprEval: \n cell_11.usr_id\n cell_11.year_month\n cell_11.hour_nbr\n cell_11.area_cty\n cell_11.basst_sel_ad\n cell_11.basst_hour\n cell_11.pvc_cd\nUnc: Varchar(50)\nUnc: Varchar(10)\nUnc: Varchar(30)\nUnc: Varchar(20)\nUnc: Varchar(20)\nUnc: Numeric(10,0)\nUnc: Varchar(20)", color = "green", shape = 第 130 页 共 182 页 "box"]; 3[label = "Recv\nRecv from: v_vertica_node0001,v_vertica_node0003\nNet id: 1000\n\nUnc: Varchar(10)\nUnc: Varchar(20)\nUnc: Varchar(30)\nUnc: Numeric(10,0)\nUnc: Varchar(20)\nUnc: Varchar(50)\nUnc: Varchar(20)", color = "green", shape = "box"]; 4[label = "Send\nSend to: v_vertica_node0001\nNet id: 1000\n\nUnc: Varchar(10)\nUnc: Varchar(20)\nUnc: Varchar(30)\nUnc: Numeric(10,0)\nUnc: Varchar(20)\nUnc: Varchar(50)\nUnc: Varchar(20)", color = "green", shape = "box"]; 5[label = "UnionAll\nUnc: Varchar(10)\nUnc: Varchar(20)\nUnc: Varchar(30)\nUnc: Numeric(10,0)\nUnc: Varchar(20)\nUnc: Varchar(50)\nUnc: Varchar(20)", color = "green", shape = "box"]; 6[label = "StorageUnionStep: cell_11_DBD_4_seg_cell_11_b1\nRLE: Varchar(10)\nRLE: Varchar(20)\nRLE: Varchar(30)\nRLE: Numeric(10,0)\nRLE: Varchar(20)\nUnc: Varchar(50)\nUnc: Varchar(20)", color = "purple", shape = "box"]; 7[label = "ScanStep: cell_11_DBD_4_seg_cell_11_b1\nyear_month RLE\npvc_cd RLE\nhour_nbr RLE\nbasst_hour RLE\narea_cty RLE\nusr_id\nbasst_sel_ad\nRLE: Varchar(10)\nRLE: Varchar(20)\nRLE: Varchar(30)\nRLE: Numeric(10,0)\nRLE: Varchar(20)\nUnc: Varchar(50)\nUnc: Varchar(20)", color = "brown", shape = "box"]; 8[label = "StorageUnionStep: cell_11_DBD_4_seg_cell_11_b0\nRLE: Varchar(10)\nRLE: Varchar(20)\nRLE: Varchar(30)\nRLE: Numeric(10,0)\nRLE: Varchar(20)\nUnc: Varchar(50)\nUnc: Varchar(20)", color = "purple", shape = "box"]; 9[label = "ScanStep: cell_11_DBD_4_seg_cell_11_b0\nyear_month RLE\npvc_cd RLE\nhour_nbr RLE\nbasst_hour RLE\narea_cty RLE\nusr_id\nbasst_sel_ad\nRLE: Varchar(10)\nRLE: Varchar(20)\nRLE: Varchar(30)\nRLE: Numeric(10,0)\nRLE: Varchar(20)\nUnc: Varchar(50)\nUnc: Varchar(20)", color = "brown", shape = "box"]; 1->0 [label = "V[0] C=7",color = "black",style="bold", arrowtail="inv"]; 2->1 [label = "0",color = "blue"]; 3->2 [label = "0",color = "blue"]; 4->3 [label = "0",color = "blue"]; 5->4 [label = "0",color = "blue"]; 6->5 [label = "0",color = "blue"]; 7->6 [label = "0",color = "blue"]; 8->5 [label = "1",color = "blue"]; 9->8 [label = "0",color = "blue"]; } (43 rows) #将 SQL 的执行计划保存到文件中 dbadmin=> \o /home/dbadmin/sql1.plan dbadmin=> explain select distinct area_cty from lizy.cell_11; dbadmin=> \o 10.3.2 理解执行计划 EXPLAIN 的输出记录了优化器选择的执行计划信息,它的原文是以树形结构展现的,优化器的每一个操作显 示为它的每一行,从执行计划可以看到以下内容:  语句中使用到的表  优化器评估的代价 第 131 页 共 182 页  优化器评估的行基数  Path ID、错误信息代码、概要计数器使得能够跟轻易的诊断性能问题  对数据的操作,如 SORT, FILTER, LIMIT, and GROUP BY  选中的 Projection  统计信息的状态信息  查询使用的算法,如 HASH/MERGE or GROUPBY HASH/GROUPBY PIPELINED  数据在集群间的再分布方式(broadcast and re-segmentation) 下面是一个实际查询的例子,主要有三个部分:  Path ID 2: STORAGE ACCESS and FILTER  Path ID 1: SORT  Path ID 0: LIMIT Vertica 建议根据《10.2.2 统计信息收集最佳实践》部分说明收集对象的统计信息,在执行计划给会给出提 示(hints)统计信息的状态信息,如统计信息缺失或过旧。 很多 SQL 语句的性能问题可以通过调用函数 ANALYZE_STATISTICS()解决;如果更新统计信息之后查询仍 第 132 页 共 182 页 然低效可以通过 DB Designer 的增量 Designer 解决;没有数据的 Projection 是不可能有全量统计信息,可以 通过表 PROJECTION_STORAGE 检查是否有数据和 PROJECTIONS 的字段 HAS_STATISTICS 是否有统计信 息;系统运行良好的情况下可以导出所有表的统计信息。 优化器会自动选择最优的 Projection 返回给查询语句,在有多个 Projection 可选的情况下,vertica 根据以 下标准选择在执行计划中使用哪个 Projection:  查询语句中列是如何关联的  Projection 的分组和排序方式  是否有分析函数操作  Projection 在磁盘存储的列的信息 需要注意的是,如果测试不同的 Projection 的效率时,在查询中使用已分段的 Projection;如果查询中使用 了未分段的 Projection,执行计划可能发生变化,因为未分段的 Projection 只在特定节点有效;为了提升查询效 率,最好让列的排序方式和 Projection 的列排序方式相同。 执行计划的关联方式,位于操作符左侧的是外层表,位于操作符右侧的是内层表。 #如下查询 T1 是外层表 SELECT * FROM T1 JOIN T2 ON T1.x = T2.x; 如果小表用作内层表,查询性能会更好,优化器会自动进行重新排序以实现这种情况除非操作符使用了 outer join。Vertica 提供 hash join 和 merge join 两种关联方式,当对象已经排序时 merge join 由于不需要预 处理,性能优,而如果对象无序且小表可以完全放入内存做 hash table 时 hash join 性能更优。 如果遇到期望使用 merge join 却得到 hash join 的情况,这是由一个 Projection 的关联列没有进行排序, 因此为了利用 merge join 往往需要创建多种对关联列排序的 Projection。 一般来说对等值关联的方式查询效率比较高,而非等值关联效率相对较低。 #1 outer join 方式示例 => EXPLAIN SELECT CD.annual_income,OSI.sale_date_key -> FROM online_sales.online_sales_fact OSI -> LEFT OUTER JOIN customer_dimension CD ON CD.customer_key = OSI.customer_key; Access Path: +-JOIN HASH [LeftOuter] [Cost: 4K, Rows: 5M] (PATH ID: 1) | Join Cond: (CD.customer_key = OSI.customer_key) | Materialize at Output: OSI.sale_date_key | Execute on: All Nodes | +-- Outer -> STORAGE ACCESS for OSI [Cost: 3K, Rows: 5M] (PATH ID: 2) | | Projection: online_sales.online_sales_fact_DBD_12_seg_vmartdb_design_vmartdb_design | | Materialize: OSI.customer_key | | Execute on: All Nodes | +-- Inner -> STORAGE ACCESS for CD [Cost: 264, Rows: 50K] (PATH ID: 3) | | Projection: public.customer_dimension_DBD_1_rep_vmartdb_design_vmartdb_design_node0001 | | Materialize: CD.annual_income, CD.customer_key | | Execute on: All Nodes 第 133 页 共 182 页 #1 merge join 方式示例 => EXPLAIN SELECT count(*) FROM online_sales.online_sales_fact OSI -> INNER JOIN customer_dimension CD ON CD.customer_key = OSI.customer_key -> INNER JOIN product_dimension PD ON PD.product_key = OSI.product_key; Access Path: +-GROUPBY NOTHING [Cost: 8K, Rows: 1] (PATH ID: 1) | Aggregates: count(*) | Execute on: All Nodes | +---> JOIN HASH [Cost: 7K, Rows: 5M] (PATH ID: 2) | | Join Cond: (PD.product_key = OSI.product_key) | | Materialize at Input: OSI.product_key | | Execute on: All Nodes | | +-- Outer -> JOIN MERGEJOIN(inputs presorted) [Cost: 4K, Rows: 5M] (PATH ID: 3) | | | Join Cond: (CD.customer_key = OSI.customer_key) | | | Execute on: All Nodes | | | +-- Outer -> STORAGE ACCESS for OSI [Cost: 3K, Rows: 5M] (PATH ID: 4) | | | | Projection: online_sales.online_sales_fact_DBD_12_seg_vmartdb_design_vmartdb_design | | | | Materialize: OSI.customer_key | | | | Execute on: All Nodes | | | +-- Inner -> STORAGE ACCESS for CD [Cost: 132, Rows: 50K] (PATH ID: 5) | | | | Projection: public.customer_dimension_DBD_1_rep_vmartdb_design_vmartdb_design_node0001 | | | | Materialize: CD.customer_key | | | | Execute on: All Nodes | | +-- Inner -> STORAGE ACCESS for PD [Cost: 152, Rows: 60K] (PATH ID: 6) | | | Projection: public.product_dimension_DBD_2_rep_vmartdb_design_vmartdb_design_node0001 | | | Materialize: PD.product_key | | | Execute on: All Nodes #以下显示等值关联代价比非等值关联低 => EXPLAIN SELECT CD.annual_income, OSI.sale_date_key -> FROM online_sales.online_sales_fact OSI -> INNER JOIN customer_dimension CD -> ON CD.customer_key = OSI.customer_key; Access Path: +-JOIN HASH [Cost: 4K, Rows: 5M] (PATH ID: 1) | Join Cond: (CD.customer_key = OSI.customer_key) | Materialize at Output: OSI.sale_date_key | Execute on: All Nodes | +-- Outer -> STORAGE ACCESS for OSI [Cost: 3K, Rows: 5M] (PATH ID: 2) | | Projection: online_sales.online_sales_fact_DBD_12_seg_vmartdb_design_vmartdb_design | | Materialize: OSI.customer_key | | Execute on: All Nodes | +-- Inner -> STORAGE ACCESS for CD [Cost: 264, Rows: 50K] (PATH ID: 3) | | Projection: public.customer_dimension_DBD_1_rep_vmartdb_design_vmartdb_design_node0001 | | Materialize: CD.annual_income, CD.customer_key | | Execute on: All Nodes => EXPLAIN SELECT CD.annual_income, OSI.sale_date_key -> FROM online_sales.online_sales_fact OSI 第 134 页 共 182 页 -> INNER JOIN customer_dimension CD -> ON CD.customer_key < OSI.customer_key; Access Path: +-JOIN HASH [Cost: 98M, Rows: 5M] (PATH ID: 1) | Join Filter: (CD.customer_key < OSI.customer_key) | Materialize at Output: CD.annual_income | Execute on: All Nodes | +-- Outer -> STORAGE ACCESS for CD [Cost: 132, Rows: 50K] (PATH ID: 2) | | Projection: public.customer_dimension_DBD_1_rep_vmartdb_design_vmartdb_design_node0001 | | Materialize: CD.customer_key | | Execute on: All Nodes | +-- Inner -> STORAGE ACCESS for OSI [Cost: 3K, Rows: 5M] (PATH ID: 3) | | Projection: online_sales.online_sales_fact_DBD_12_seg_vmartdb_design_vmartdb_design | | Materialize: OSI.sale_date_key, OSI.customer_key | | Execute on: All Nodes => EXPLAIN SELECT * FROM hTicks h FULL OUTER JOIN aTicks a -> ON h.time INTERPOLATE PREVIOUS VALUE a.time Access Path: +-JOIN (INTERPOLATED) [FullOuter] [Cost: 31, Rows: 4 (NO STATISTICS)] (PATH ID: 1) Outer (SORT ON JOIN KEY) Inner (SORT ON JOIN KEY) | Join Cond: (h."time" = a."time") | Execute on: Query Initiator | +-- Outer -> STORAGE ACCESS for h [Cost: 15, Rows: 4 (NO STATISTICS)] (PATH ID: 2) | | Projection: public.hTicks_node0004 | | Materialize: h.stock, h."time", h.price | | Execute on: Query Initiator | +-- Inner -> STORAGE ACCESS for a [Cost: 15, Rows: 4 (NO STATISTICS)] (PATH ID: 3) | | Projection: public.aTicks_node0004 | | Materialize: a.stock, a."time", a.price | | Execute on: Query Initiator Vertica 提供了三种算法的 group by 操作  GROUPBY PIPELINED:要求在进行 group by 操作的列事先排序,这是优化器最优考虑的 group by 方式,因为它可以直接取数据,不需要 hash 表做内存排序,消耗内存少。  GROUPBY HASH:由于数据在进行分组的列未排序,所有需要先创建 hash 表存入进行分组 的列数据集合。  GROUPBY:部分数据已排序的情况下使用这种方式,比如一个或者多个进行分组的列未排序, 可以包含或者不包含 distinct,这种算法使用比较小的 hash 表以减少内存或者磁盘的使用。 关于数据分布上,前面提到它有两种方式,广播(broadcasts)和重新分段(resegments),广播是把中 间结果的完整拷贝复制到所有节点上。以下情况会使用到广播机制:  其中一个表非常小,一般来说是内层表 第 135 页 共 182 页  Vertica 可以避免上游大数据的重新分段  外层表或者子查询需要关联的一方被复制 重新分段把现成的 Projection 或者中间关系和分段数据均匀的分发到每个节点,重新分段结束,满足输入条 件的每一行数据在特定的某一个节点,它一般会用在数据未分段的本地关联的分布式关联上。 10.4 使用 profile 如果需要获得查询执行的时间等信息时,使用概要(profile),和 EXPLAIN 不同的是,后者所有代价数据 都是基于对 SQL 语句的评估得来,而概要中的数据都是实际执行的结果,概要信息包含:  Projection 设计的问题,如分段和排序  查询是否受限于网络  每一个操作分配了多少的内存  查询重写是否可以加快查询速度  每一个操作使用了多少个线程执行  在查询的整个生命周期中数据在各操作间的流向 Real-time profiling 总是打开的,不需要显示打开,概要数据在下面情况都是存在的,任何明确使用了概要 的查询语句和任何正在执行的查询语句。 从系统表 EXECUTION_ENGINE_PROFILES 可以查询每一个 SQL 的执行详细信息,如果没有启用概要这 这个表没有数据;QUERY_PROFILES 和 QUERY_PLAN_PROFILES 可以获得查询的基本信息,如果 SQL 文 本,执行时间等;SESSION_PROFILES 提供进程的参数和锁超时信息。 dbadmin=> SELECT SHOW_PROFILING_CONFIG(); SHOW_PROFILING_CONFIG -------------------------------------------------------- Session Profiling: Local off, Global off EE Profiling: Local off, Global off Query Profiling: Local off, Global off (1 row) 10.4.1 打开关闭 profile 对当前的 session 打开 profile 可以使用函数 ENABLE_PROFILING()完成,它可以有三种类型的 profile, 分别是:session 对进程的参数和锁超时情况打开 profile;query 对查询的基本信息打开 profile;ee 对查询引 擎打开 profile,记录 SQL 执行的详细信息。 第 136 页 共 182 页 相应的关闭当前 session 的 profile 使用 DISABLE_PROFILING()实现,类型和前面一样。 #对 ee 打开 profile dbadmin=> SELECT ENABLE_PROFILING('ee'); ENABLE_PROFILING ---------------------- EE Profiling Enabled (1 row) dbadmin=> SELECT SHOW_PROFILING_CONFIG(); SHOW_PROFILING_CONFIG ------------------------------------------------------------ Session Profiling: Local off, Global off EE Profiling: Local on, Global off Query Profiling: Local off, Global off (1 row) #对 ee 关闭 profile dbadmin=> select DISABLE_PROFILING('ee'); DISABLE_PROFILING ----------------------- EE Profiling Disabled (1 row) dbadmin=> SELECT SHOW_PROFILING_CONFIG(); SHOW_PROFILING_CONFIG ----------------------------------------------------------- Session Profiling: Local off, Global off EE Profiling: Local off, Global on Query Profiling: Local off, Global off (1 row) 如果需要对所有节点的所有进程打开 profile,执行 SET_CONFIG_PARAMETER,它相应的也有三种类型, 分别是 GlobalSessionProfiling、GlobalQueryProfiling、GlobalEEProfiling,含义和前面的类似。 #第二个参数为 1 表示打开,为 0 关闭 dbadmin=> SELECT SET_CONFIG_PARAMETER('GlobalEEProfiling',1); SET_CONFIG_PARAMETER ---------------------------- Parameter set successfully (1 row) dbadmin=> dbadmin=> SELECT SHOW_PROFILING_CONFIG(); SHOW_PROFILING_CONFIG ---------------------------------------------------------- Session Profiling: Local off, Global off EE Profiling: Local on, Global on Query Profiling: Local off, Global off (1 row) 第 137 页 共 182 页 dbadmin=> SELECT SET_CONFIG_PARAMETER('GlobalEEProfiling',0); SET_CONFIG_PARAMETER ---------------------------- Parameter set successfully (1 row) dbadmin=> SELECT SHOW_PROFILING_CONFIG(); SHOW_PROFILING_CONFIG ------------------------------------------------------------- Session Profiling: Local off, Global off EE Profiling: Local off, Global off Query Profiling: Local off, Global off (1 row) 10.4.2 Real-time profiling 它提供了一种监控长查询的手段,对所有的执行语句包括内部操作,如 mergeout、recover、refresh。由 于它只在 SQL 执行时提供,除非使用了 PROFILE 关键字或者使用函数 ENABLE_PROFILING,否则 SQL 执行 结束后概要信息就无法查到。 系统表 EXECUTION_ENGINE_PROFILES 可以获得内部操作和用户语句的概要信息,诸如执行时间 (us)、处理的行数、总共的 merge 阶段、完成的 merge 阶段、当前使用的 temp file 大小(字节)。 而如果想知道某一个特定操作的消耗的话,可以查询系统表 QUERY_PLAN_PROFILES 观察执行计划中的 实时数据流。 #消耗最高的 10 个操作 dbadmin=> SELECT node_name, operator_name, counter_value execution_time_us FROM v_monitor.execution_engine_profiles WHERE counter_name='execution time (us)' ORDER BY node_name, counter_value DESC limit 10; node_name | operator_name | execution_time_us --------------------+---------------+------------------- v_vertica_node0001 | Scan | 155607388 v_vertica_node0001 | Scan | 44010108 v_vertica_node0001 | Scan | 43592413 v_vertica_node0001 | Scan | 17904994 v_vertica_node0001 | Scan | 17662862 v_vertica_node0001 | Scan | 15418187 v_vertica_node0001 | DataTarget | 14516786 v_vertica_node0001 | DataTarget | 12223069 v_vertica_node0001 | Scan | 12007167 v_vertica_node0001 | Scan | 10546916 (10 rows) 第 138 页 共 182 页 10.4.3 使用 vsql 管理 profile 想要对一条语句使用 profile,只需要在语句开头增加 PROFILE 关键字即可。语句运行的过程中会有一个提 示输出到终端, #profile 查询 dbadmin=> profile select count(distinct usr_id) from lizy.cell_11; NOTICE 4788: Statement is being profiled HINT: Select * from v_monitor.execution_engine_profiles where transaction_id=49539595901373320 and statement_id=8; NOTICE 3557: Initiator memory for query: [on pool general: 503403 KB, minimum: 503403 KB] NOTICE 5077: Total memory required by query: [503403 KB] count -------- 459049 (1 row) #使用 Linux 的 watch 命令监控 [dbadmin@V2 v_vertica_node0002_catalog]$ watch -n 1 -d "vsql -U dbadmin -w 123456 -c \"select count(distinct usr_id) from lizy.cell_11\"" Every 1.0s: vsql -U dbadmin -w 123456 -c "select count(distinct usr_id) from lizy.cell_11" Fri Aug 22 15:11:30 2014 count -------- 459049 (1 row) #如下脚本提供了分析所有分析计算器(profiling counter)的示例 dbadmin=> \i /opt/vertica/scripts/demo_eeprof_view.sql add_vertica_options --------------------- Options Set (1 row) CREATE SCHEMA clr_vertica_options --------------------- (1 row) CREATE VIEW CREATE VIEW CREATE VIEW CREATE VIEW 第 139 页 共 182 页 CREATE VIEW CREATE VIEW CREATE VIEW CREATE VIEW CREATE VIEW CREATE VIEW CREATE VIEW CREATE VIEW CREATE VIEW CREATE VIEW CREATE VIEW CREATE VIEW CREATE VIEW CREATE VIEW CREATE VIEW CREATE VIEW CREATE VIEW CREATE VIEW CREATE VIEW CREATE VIEW CREATE VIEW CREATE VIEW CREATE VIEW CREATE VIEW CREATE VIEW CREATE VIEW CREATE VIEW CREATE VIEW CREATE VIEW CREATE VIEW 为了方便给定位 profile,可以通过提示的方式给 profile 加一个标签,标签可以包含字母、数字、下划线、 美元符号,最大长度 128 位,但是不能包含空格和以数字开头。 #以下都是有效的标签 dbadmin=> SELECT /*+label(myselectquery)*/ COUNT(*) FROM t; COUNT ------- 0 (1 row) dbadmin=> INSERT /*+label(myinsertquery)*/ INTO t VALUES(1); OUTPUT -------- 1 (1 row) 第 140 页 共 182 页 dbadmin=> UPDATE /*+label(myupdatequery)*/ t SET id = 2 WHERE id = 1; OUTPUT -------- 1 (1 row) dbadmin=> DELETE /*+label(mydeletequery)*/ FROM t WHERE id = 1; OUTPUT -------- 0 (1 row) dbadmin=> SELECT /*+ label(abc123) */table_name FROM system_tables LIMIT 5; table_name --------------------------------------- nodes user_transforms materialize_flextable_columns_results license_audits types (5 rows) dbadmin=> SELECT identifier, query FROM query_profiles where query like '%/*+label%'; identifier | query ---------------+----------------------------------------------------------------------------- myselectquery | SELECT /*+label(myselectquery)*/ COUNT(*) FROM t; myinsertquery | INSERT /*+label(myinsertquery)*/ INTO t VALUES(1); myupdatequery | UPDATE /*+label(myupdatequery)*/ t SET id = 2 WHERE id = 1; mydeletequery | DELETE /*+label(mydeletequery)*/ FROM t WHERE id = 1; | SELECT identifier, query FROM query_profiles where query like '%/*+label%'; (5 rows) 10.5 优化查询语句 查询的运行时间主要依赖于查询的复杂度、执行计划中操作的多少、数据量、Projection 的设计,如果查询 遇到 CPU、IO 瓶颈,那么效率往往会变低。大部分情况下,CPU 使用高可以通过 Projection 的设计缓解,而 IO 瓶颈往往是由于 sort、order 操作导致数据溢出所致。 要知道查询为何慢的原因,可以通过使用 EXPLAIN 检测咨询计划;通过访问系统表 EXECUTION_ENGIN E_PROFILES 检测咨询计划,通过执行计划分析往往可以看出是否使用了非优化的 Projection、是否在非排序列 或者未编码列使用了谓词,抑或是使用了 hash group by 而不是 group by pipeline。 SQL 语句性能优化的第一步是需要运行 DB Designer,DB Designer 创建对象的物理模式以便为查询提供 优化,当运行 DB Designer 时选择更新统计信息选项,统计信息可以帮助决定选择合适的 Projection、最佳的 关联方式和排序、数据分布机制。 第 141 页 共 182 页 查询表 QUERY_EVENTS 检查是否在执行计划阶段出现问题,EVENT_TYPE 字段说明出现的问题类型, PREDICATE OUTSIDE HISTOGRAM:谓词在直方图信息之外;NO HISTOGRAM:没有直方图信息; MEMORY LIMIT HIT:优化器使用所有可用内存去创建执行计划,遇到该错误需要简化 SQL 语句而不是增加内 存。 10.5.1 优化编码方式 编码方式的改变可以减少磁盘数据大小,进而减少读取数据的 IO,潜在的结果是加快了查询语句。所以要确 定所有出现在查询的列都使用了正确的编码方式,参考以下步骤完成编码方式的优化:  运行 DB Designer 进行增量的设计  增量设计之后,运行 ANALYZE_STATISTICS 收集统计信息  对增量设计的 SQL 运行 EXPLAIN 以验证是否使用了新的 Projection 可以通过函数 DESIGNER_DESIGN_PROJECTION_ENCODINGS 评估当前对象的编码是否合适,以及是否需要更新。 #该函数的语法如下: DESIGNER_DESIGN_PROJECTION_ENCODINGS ('projection_list','projection_ddl_script_file,'deploy') #检查 ods_ucm 用户下编码方式不合适的表 dbadmin=> SELECT DESIGNER_DESIGN_PROJECTION_ENCODINGS ( dbadmin(> 'ods_ucm.*', dbadmin(> 'encodings.sql', dbadmin(> 'false' dbadmin(> ); WARNING 4888: Table ods_ucm.tmp_appage has no statistics or data. As a result, the proposed projections on this table may be suboptimal HINT: Load data or statistics into this table DESIGNER_DESIGN_PROJECTION_ENCODINGS -------------------------------------- (1 row) 默认生成的文件放在 catalog 目录,如:/home/dbadmin/dws/v_dws_node0001_catalog/encodings.sql 如果发现在浮点型(FLOAT)的列上出现性能或者存储压力时,根据业务的评估检查是否可以通过 18 位或 者更少的数值型(NUMERIC)列来替换,数值型列能提高压缩比进而减少磁盘数据大小,以提升性能。使用数 值型列时指定长度和精度,这样数值型就精确代表一个数据,而浮点型数据只大概代表一个数据。在以下情形下 把浮点型数据转换为数值型数据效率更高:  数值型数据的精度小于或等于 18 位,vertica 不太建议对超过 18 位的浮点型数据做转换; 第 142 页 共 182 页  浮点型数据是有界限的,其值会落在数值型数据列的某一个精度范围。比如存放钱的列,像产品 标价、金融交易额,如果一个列定义为 NUMERIC(11,2),可以存放 0 到百万级别的数据,显然 存放分(美分: cents)时压缩比比浮点型高。 对于基数少的列使用 RLE 编码能有效的降低数据存储大小和提升查询性能,而且最好平均重复度大于 10, 平均重复度小于 8 不适合使用 RLE 编码。 10.5.2 优化带谓词的查询 Projection 如果查询中包含一个或者多个谓词,可以通过 Projection 优化查询效率,参考以下两个例子: #示例 1、查询使用了时间范围 如下使用 RLE 编码和改变 Projection 的排序方式提升查询区间数据的效率 SELECT * FROM trades WHERE trade_date BETWEEN '2007-11-01' AND '2007-12-01'; 为了优化这条语句,检查是否所有的 Projection 都可以以一种时间方式查询,对每个 Projection 运行 SELECT COUNT(*)并指定 时间范围,观察执行时间。如果一个或者多个查询较慢,检查 trade_date 列数据的唯一性并决定是否需要对其在 Projection 中进 行排序或者使用 RLE 编码,RLE 编码把重复的数据序列替换成数据值和重复度的组合。为了实现最优,排序时按低基数到高基数列 顺序进行,使用 RLE 编码的列明显是属于低基数列。 如果唯一性的列未排序,或者重复度小于 10,就是说 trade_date 太接近唯一,但是又不能使用 RLE 编码,这种情况下增加一个列 减少数据扫描范围。如检查下面新增加的列 trade_year 是否返回一组可控的数据,如下查询数据按 trade_year 分组。 SELECT DATE_TRUNC('trade_year', trade_date), COUNT(*) FROM trades GROUP BY DATE_TRUNC('trade_year',trade_date); 假定 trade_year = 2007 数据有 8k,增加该列之后查询变成如下,这样就可以创建一个 Projection 按 trade_year 排序,并使用 RLE 编码。 SELECT * FROM trades WHERE trade_year = 2007 AND trade_date BETWEEN '2007-11-01' AND '2007-12-01'; #示例 2、查询高基数主键列 如下示例演示如果通过修改 Projection 提高基于高基数的主键列的查询效率 考虑以下的查询: SELECT FROM [table] WHERE pk IN (12345, 12346, 12347,...); 由于主键基数太大,vertica 必须要扫描大量数据才能返回结果,要优化这样的查询,同样创建一个新的列,该列以主键列除以 10000 得出,然后原来的查询将变成这样 SELECT FROM [table] WHERE buckets IN (1,...) AND pk IN (12345, 12346, 12347,...); 谓词中包含了低基数的列,如果创建一个 Projection,其中 buckets 在排序的前面,那么查询将明显变快。 如以下示例所示: dbadmin=> alter table ods_ucm.cell_11 add column v_usr_id varchar; 第 143 页 共 182 页 ALTER TABLE Time: First fetch (0 rows): 4302.529 ms. All rows formatted: 4302.798 ms dbadmin=> update ods_ucm.cell_11 set v_usr_id=left(usr_id,3); OUTPUT ---------- 19999970 (1 row) Time: First fetch (1 row): 840916.902 ms. All rows formatted: 840979.221 ms dbadmin=> commit; COMMIT Time: First fetch (0 rows): 5275.882 ms. All rows formatted: 5275.898 ms dbadmin=> select count(1) from ods_ucm.cell_11 where usr_id='006FBE14355F72C82CDCEF8FCD677486'; count ------- 1 (1 row) Time: First fetch (1 row): 19076.603 ms. All rows formatted: 19076.641 ms dbadmin=> select count(1) from ods_ucm.cell_11 where v_usr_id='006' and usr_id='006FBE14355F72C82CDCEF8FCD677486'; count ------- 1 (1 row) Time: First fetch (1 row): 15604.913 ms. All rows formatted: 15604.975 ms 根据上面的查询创建 Projection 之后的速度 dbadmin=> select count(1) from ods_ucm.cell_11 where v_usr_id='006' and usr_id='006FBE14355F72C82CDCEF8FCD677486'; count ------- 1 (1 row) Time: First fetch (1 row): 59.983 ms. All rows formatted: 60.017 ms dbadmin=> select count(1) from ods_ucm.cell_11 where v_usr_id='007' and usr_id='00736FC6AC2E1FC99FCD8ED2F808BB13'; count ------- 0 (1 row) Time: First fetch (1 row): 59.871 ms. All rows formatted: 59.925 ms select count(1) from ods_ucm.cell_11 where v_usr_id='007' and usr_id='00736FC6AC2E1FC99FCD8ED2F808BB13'; 创建的 Projection 语句: [dbadmin@V1 dba]$ more cell_11_deploy.sql CREATE PROJECTION cell_11_DBD_1_seg_cell_11_b0 /*+basename(cell_11_DBD_1_seg_cell_11),createtype(D)*/ 第 144 页 共 182 页 ( usr_id ENCODING AUTO, hour_nbr ENCODING AUTO, v_usr_id ENCODING RLE ) AS SELECT usr_id, hour_nbr, v_usr_id FROM ods_ucm.cell_11 ORDER BY v_usr_id, usr_id SEGMENTED BY MODULARHASH (usr_id) ALL NODES OFFSET 0; CREATE PROJECTION cell_11_DBD_1_seg_cell_11_b1 /*+basename(cell_11_DBD_1_seg_cell_11),createtype(D)*/ ( usr_id ENCODING AUTO, hour_nbr ENCODING AUTO, v_usr_id ENCODING RLE ) AS SELECT usr_id, hour_nbr, v_usr_id FROM ods_ucm.cell_11 ORDER BY v_usr_id, usr_id SEGMENTED BY MODULARHASH (usr_id) ALL NODES OFFSET 1; select refresh('ods_ucm.cell_11'); 10.5.3 优化 merge 操作的 Projection Vertica 的优化器会自动为查询选择最优的 Projection,但是 DBA 或者开发人员还是可以通过检查和确保 Projection 是最优化设计的。好的 Projection 可以让 vertica 直接选择 merge join 操作源表和目标表之间不需 要额外排序和数据转移操作的高效的关联方式。 为了达到这个效果,vertica 的建议是先运行 DB Designer 进行完整的设计,然后根据实际情况进行增量的 设计。考虑下面的例子,想要根据源表的 b 列插入或者更新到目标表的 a 列,vertica 在满足以下条件中的至少一 个的情况下可以使用本地 merge join(local merge join),且输入数据是事先排序的。 #考虑以下 merge 操作 MERGE INTO target t USING source s ON t.a = s.b WHEN ....  对于复制的 Projection 在目标表的 a 列排序,源表的 b 列排序  对于分段的 Projection 在目标表的 a 列、源表的 b 列以及相应的分段列相等的分段 第 145 页 共 182 页 提示:另外源表比目标表小的情况下 merge 性能更优 以下对比优化的和非优化的 merge 操作,在满足以下情况是 vertica 使用优化的 merge 操作:  目标表的关联列有主键或者唯一键  目标表包含所有的插入或更新子句列  插入或更新子句列的属性是相等的 提示:并不要求源表的关联列也有主键或唯一键,而且源表可以包含比目标表更多的列,只要插入或更新子 句的列和列属性跟目标表相同即可。 如何判断 merge 操作是否优化的?在 merge 语句前使用 EXPLAIN 关键字,检查输出结果,如果出现 Semi 路径访问说明是优化的 merge,如果出现 Right Outer 路径说明是非优化的 merge,merge 操作会跟之前版本的 性能相同直到 merge 的查询语句遇到重复值。 即便是满足了 merge 优化的条件,在执行时如果遇到关联列上的重复值,仍然可能报出运行时的错误并失败。 为了让 merge 操作满足优化条件,vertica 生成优化的执行计划时会强制启用关联列的主键或者唯一键,否则会 出现下面的情景,源表有超过一个满足目标表关联条件的相应的值,此时报运行时错误而失败;目标表有超过一 个的满足源表关联条件的相应的值,如果目标表有主键或者唯一键约束报运行时错误,如果没有唯一键约束正常 运行,但是并非优化的 merge 方式。 dbadmin=> CREATE TABLE target(a INT PRIMARY KEY, b INT, c INT) ORDER BY b,a; CREATE TABLE source(a INT, b INT, c INT) ORDER BY b,a; INSERT INTO target VALUES(1,2,3); INSERT INTO target VALUES(2,4,7); INSERT INTO source VALUES(3,4,5); INSERT INTO source VALUES(4,6,9); COMMIT; CREATE TABLE dbadmin=> CREATE TABLE source(a INT, b INT, c INT) ORDER BY b,a; CREATE TABLE dbadmin=> INSERT INTO target VALUES(1,2,3); OUTPUT -------- 1 (1 row) dbadmin=> INSERT INTO target VALUES(2,4,7); OUTPUT -------- 1 (1 row) dbadmin=> INSERT INTO source VALUES(3,4,5); OUTPUT -------- 第 146 页 共 182 页 1 (1 row) dbadmin=> INSERT INTO source VALUES(4,6,9); OUTPUT -------- 1 (1 row) dbadmin=> COMMIT; #以下语句满足优化的 merge 的条件 目标表的关联列有主键 所有目标表的列都包括在更新插入语句中 插入、更新列的属性相等 EXPLAIN MERGE INTO target t USING source s ON t.a = s.a WHEN MATCHED THEN UPDATE SET a=s.a, b=s.b, c=s.c WHEN NOT MATCHED THEN INSERT(a,b,c) VALUES(s.a,s.b,s.c); Access Path: +-DML DELETE [Cost: 0, Rows: 0] | Target Projection: public.target_b1 (DELETE ON CONTAINER) | Target Prep: | Execute on: All Nodes | +---> JOIN HASH [Semi] [Cost: 7, Rows: 2 (NO STATISTICS)] (PATH ID: 1) Inner (RESEGMENT) | | Join Cond: (t.a = VAL(2)) | | Execute on: All Nodes | | +-- Outer -> STORAGE ACCESS for t [Cost: 2, Rows: 2 (NO STATISTICS)] (PATH ID: 2) | | | Projection: public.target_b1 | | | Materialize: t.a | | | Execute on: All Nodes | | | Runtime Filter: (SIP1(HashJoin): t.a) | | +-- Inner -> SELECT [Cost: 3, Rows: 2 (NO STATISTICS)] (PATH ID: 3) | | | Execute on: All Nodes | | | +---> STORAGE ACCESS for s [Cost: 3, Rows: 2 (NO STATISTICS)] (PATH ID: 4) | | | | Projection: public.source_b0 | | | | Materialize: s.a | | | | Execute on: All Nodes +-Target Projection: public.target_b0 (DELETE ON CONTAINER) | Target Prep: | Execute on: All Nodes | +---> JOIN HASH [Semi] [Cost: 7, Rows: 2 (NO STATISTICS)] (PATH ID: 1) Inner (RESEGMENT) | | Join Cond: (t.a = VAL(2)) | | Execute on: All Nodes | | +-- Outer -> STORAGE ACCESS for t [Cost: 2, Rows: 2 (NO STATISTICS)] (PATH ID: 2) | | | Projection: public.target_b0 | | | Materialize: t.a | | | Execute on: All Nodes | | | Runtime Filter: (SIP2(HashJoin): t.a) 第 147 页 共 182 页 | | +-- Inner -> SELECT [Cost: 3, Rows: 2 (NO STATISTICS)] (PATH ID: 3) | | | Execute on: All Nodes | | | +---> STORAGE ACCESS for s [Cost: 3, Rows: 2 (NO STATISTICS)] (PATH ID: 4) | | | | Projection: public.source_b0 | | | | Materialize: s.a | | | | Execute on: All Nodes dbadmin=> MERGE INTO target t USING source s ON t.a = s.a dbadmin-> WHEN MATCHED THEN UPDATE SET a=s.a, b=s.b, c=s.c dbadmin-> WHEN NOT MATCHED THEN INSERT(a,b,c) VALUES(s.a,s.b,s.c); OUTPUT -------- 2 (1 row) #以下是非优化的 merge 的例子: explain MERGE INTO target t USING source s ON t.a = s.a WHEN MATCHED THEN UPDATE SET a=s.a + 1, b=s.b, c=s.c - 1 WHEN NOT MATCHED THEN INSERT(a,b,c) VALUES(s.a,s.b,s.c); Access Path: +-DML MERGE [Cost: 0, Rows: 0] | Target Projection: public.target_b1 | Target Projection: public.target_b0 | Target Prep: | Execute on: All Nodes | +---> JOIN HASH [RightOuter] [Cost: 18, Rows: 2 (NO STATISTICS)] (PATH ID: 1) Inner (RESEGMENT) | | Join Cond: (target.a = VAL(2)) | | Execute on: All Nodes | | +-- Outer -> STORAGE ACCESS for [Cost: 7, Rows: 2 (NO STATISTICS)] (PATH ID: 2) | | | Projection: public.target_b0 | | | Materialize: target.b, target.a, target.c, target.epoch | | | Execute on: All Nodes | | | Runtime Filter: (SIP1(HashJoin): target.a) | | +-- Inner -> SELECT [Cost: 9, Rows: 2 (NO STATISTICS)] (PATH ID: 3) | | | Execute on: All Nodes | | | +---> STORAGE ACCESS for s [Cost: 9, Rows: 2 (NO STATISTICS)] (PATH ID: 4) | | | | Projection: public.source_b0 | | | | Materialize: s.b, s.a, s.c | | | | Execute on: All Nodes #将上面的 merge 语句变成优化的 merge explain MERGE INTO target t USING source s ON t.a = s.a WHEN MATCHED THEN UPDATE SET a=s.a + 1, b=s.b, c=s.c -1 WHEN NOT MATCHED THEN INSERT(a,b,c) VALUES(s.a + 1, s.b, s.c - 1); Access Path: +-DML DELETE [Cost: 0, Rows: 0] 第 148 页 共 182 页 | Target Projection: public.target_b1 (DELETE ON CONTAINER) | Target Prep: | Execute on: All Nodes | +---> JOIN HASH [Semi] [Cost: 7, Rows: 2 (NO STATISTICS)] (PATH ID: 1) Inner (RESEGMENT) | | Join Cond: (t.a = VAL(2)) | | Execute on: All Nodes | | +-- Outer -> STORAGE ACCESS for t [Cost: 2, Rows: 2 (NO STATISTICS)] (PATH ID: 2) | | | Projection: public.target_b1 | | | Materialize: t.a | | | Execute on: All Nodes | | | Runtime Filter: (SIP1(HashJoin): t.a) | | +-- Inner -> SELECT [Cost: 3, Rows: 2 (NO STATISTICS)] (PATH ID: 3) | | | Execute on: All Nodes | | | +---> STORAGE ACCESS for s [Cost: 3, Rows: 2 (NO STATISTICS)] (PATH ID: 4) | | | | Projection: public.source_b0 | | | | Materialize: s.a | | | | Execute on: All Nodes +-Target Projection: public.target_b0 (DELETE ON CONTAINER) | Target Prep: | Execute on: All Nodes | +---> JOIN HASH [Semi] [Cost: 7, Rows: 2 (NO STATISTICS)] (PATH ID: 1) Inner (RESEGMENT) | | Join Cond: (t.a = VAL(2)) | | Execute on: All Nodes | | +-- Outer -> STORAGE ACCESS for t [Cost: 2, Rows: 2 (NO STATISTICS)] (PATH ID: 2) | | | Projection: public.target_b0 | | | Materialize: t.a | | | Execute on: All Nodes | | | Runtime Filter: (SIP2(HashJoin): t.a) | | +-- Inner -> SELECT [Cost: 3, Rows: 2 (NO STATISTICS)] (PATH ID: 3) | | | Execute on: All Nodes | | | +---> STORAGE ACCESS for s [Cost: 3, Rows: 2 (NO STATISTICS)] (PATH ID: 4) | | | | Projection: public.source_b0 | | | | Materialize: s.a | | | | Execute on: All Nodes 10.5.4 优化 group by 子句 部分排序的数据进行 group by 操作查询当其 Projection 按其聚合列的子集进行排序时能够得到优化。当对 包含大量数据的表进行聚合查询,vertica 自动使用部分排序的 group by 方式优化以减少或避免 hash 表数据在 查询过程中需要入磁盘。 这种优化方式对包含两个或多个 DISTINCT 聚合函数,如果 count、sum 等。部分排序的 group by 方式优 化对于表数据较少,能够全部放入内存 hash 表中的情况不适合。 #考虑下嘛 VMart 的例子 $ cd /opt/vertica/examples/VMart_Schema $ ls vmart_gen $ vsql 第 149 页 共 182 页 -- create and populate the example tables from the .tbl files =>\i vmart_create_schema.sql =>\i vmart_load_data.sql -- verify table population => SELECT COUNT(*) FROM store.store_sales_fact; COUNT --------- 5000000 (1 row) => CREATE PROJECTION store.store_sales_fact_by_store_and_date AS SELECT * FROM store.store_sales_fact f ORDER BY f.store_key, f.date_key; => SELECT START_REFRESH(); -- wait a few seconds before running queries 查询优化器使用部分排序的 group by 优化,因为 store_key 是 Projection 其中排序的列之一,查询包含了多个对 distinct 使用 聚合函数。 VMart=> EXPLAIN SELECT COUNT(distinct customer_key) AS cntd_cust, store_key, COUNT(DISTINCT product_key) AS cntd_prod, COUNT(DISTINCT promotion_key) AS cntd_promo, SUM(sales_dollar_amount) AS sum_sales_dollar, SUM(cost_dollar_amount) AS sum_cost_dollar FROM store.store_sales_fact GROUP BY store_key ORDER BY cntd_cust DESC LIMIT 25;Access Path:+-SELECT LIMIT 25 [Cost: 43K, Rows: 25 (NO STATISTICS)] (PATH ID: 0) | Output Only: 25 tuples | +---> SORT [TOPK] [Cost: 43K, Rows: 10K (NO STATISTICS)] (PATH ID: 1) | | Order: "Sqry$_1".cntd_cust DESC | | Output Only: 25 tuples | | +---> JOIN MERGEJOIN(inputs presorted) [Cost: 43K, Rows: 10K (NO STATISTICS)] (PATH ID: 2) | | | Join Cond: ("Sqry$_2".store_key <=> "Sqry$_3".store_key) | | | +-- Outer -> JOIN MERGEJOIN(inputs presorted) [Cost: 32K, Rows: 10K (NO STATISTICS)] (PATH ID: 3) | | | | Join Cond: ("Sqry$_1".store_key <=> "Sqry$_2".store_key) | | | | +-- Outer -> SELECT [Cost: 22K, Rows: 10K (NO STATISTICS)] (PATH ID: 4) | | | | | +---> GROUPBY HASH (SORT OUTPUT) (LOCAL RESEGMENT GROUPS) [Cost: 22K, Rows: 10K (NO STATISTICS)] (PATH ID: 5) | | | | | Aggregates: count(DISTINCT store_sales_fact.customer_key), sum(), sum() | | | | | | Group By: store_sales_fact.store_key | | | | | | Partially sorted keys: 1 | | | | | | +---> GROUPBY HASH (LOCAL RESEGMENT GROUPS) [Cost: 22K, Rows: 10K (NO STATISTICS)] (PATH ID: 6) | | | | | | | Aggregates: sum(store_sales_fact.sales_dollar_amount), sum(store_sales_fact.cost_dollar_amount) | | | | | | | Group By: store_sales_fact.store_key, store_sales_fact.customer_key | | | | | | | Partially sorted keys: 1 | | | | | | | +---> STORAGE ACCESS for store_sales_fact [Cost: 18K, Rows: 5M (NO STATISTICS)] (PATH ID: 7) ... 如果查询包含 groupby 子句,那么 vertica 要么使用 groupby pipelined 或者 groupby hash 算法进行处 理。如果处理的结果是生成一小部分 distinct 数据(比如集群的每个节点 1 千个),那么两种算法性能和结果表 现差异不大。但是对于处理大量数据来说,groupby pipelined 使用较少内存,性能更高,但是要求数据必须事 先排序的。 第 150 页 共 182 页 对于处理大量 distinct 数据的 groupby 操作,可以通过下面的方法来使查询从 groupby hash 转换成 groupby pipelined 提升性能。 #考虑下面的这个例子,主要有三个条件 CREATE TABLE sortopt ( a INT NOT NULL, b INT NOT NULL, c INT, d INT ); CREATE PROJECTION sortopt_p ( a_proj, b_proj, c_proj, d_proj ) AS SELECT * FROM sortopt ORDER BY a,b,c UNSEGMENTED ALL NODES; INSERT INTO sortopt VALUES(5,2,13,84); INSERT INTO sortopt VALUES(14,22,8,115); INSERT INTO sortopt VALUES(79,9,401,33); #条件 1、所有出现在查询的 groupby 子句的列都必须出现在 Projection 的排序列。如上 Projection 的排序列 未 a、b、c GROUP BY a GROUP BY a,b GROUP BY b,a GROUP BY a,b,c GROUP BY c,a,b 使用 groupby pipelined GROUP BY a,b,c,d 使用 groupby hash,因为 d 列未出现在 Projection 的排序列 中。 #条件 2、查询的 groupby 子句的列少于 Projection 的排序列,且 groupby 子句的列以 occur first (Projection 排序列的一部分或全部以相邻位置出现在 groupby 中,可以顺序或反序)方式出现在 Projection 排序列。 GROUP BY a GROUP BY a,b GROUP BY b,a GROUP BY a,b,c 使用 groupby pipelined 第 151 页 共 182 页 GROUP BY c,a,b GROUP BY a,c 使用 groupby hash , 因 为 未 以 occur first 方式出现在 Projection 的排序列中。 explain select a,b,count(c) from sortopt group by a,b; Access Path: +-GROUPBY PIPELINED [Cost: 16, Rows: 3 (NO STATISTICS)] (PATH ID: 1) | Aggregates: count(sortopt.c) | Group By: sortopt.a, sortopt.b | Execute on: Query Initiator | +---> STORAGE ACCESS for sortopt [Cost: 15, Rows: 3 (NO STATISTICS)] (PATH ID: 2) | | Projection: public.sortopt_p_node0001 | | Materialize: sortopt.a, sortopt.b, sortopt.c | | Execute on: Query Initiator explain select a,c,b,count(d) from sortopt group by a,c,b; Access Path: +-GROUPBY PIPELINED [Cost: 21, Rows: 3 (NO STATISTICS)] (PATH ID: 1) | Aggregates: count(sortopt.d) | Group By: sortopt.a, sortopt.b, sortopt.c | Execute on: Query Initiator | +---> STORAGE ACCESS for sortopt [Cost: 20, Rows: 3 (NO STATISTICS)] (PATH ID: 2) | | Projection: public.sortopt_p_node0001 | | Materialize: sortopt.a, sortopt.b, sortopt.c, sortopt.d | | Execute on: Query Initiator explain select a,c,count(b) from sortopt group by a,c; Access Path: +-GROUPBY HASH (LOCAL RESEGMENT GROUPS) [Cost: 16, Rows: 3 (NO STATISTICS)] (PATH ID: 1) | Aggregates: count(sortopt.b) | Group By: sortopt.a, sortopt.c | Partially sorted keys: 1 | Execute on: Query Initiator | +---> STORAGE ACCESS for sortopt [Cost: 15, Rows: 3 (NO STATISTICS)] (PATH ID: 2) | | Projection: public.sortopt_p_node0001 | | Materialize: sortopt.a, sortopt.b, sortopt.c | | Execute on: Query Initiator #条件 3、如果查询的 groupby 子句的列未以 appear first(和 occur first 含义类似,Projection 排序列的一部 分或全部以相邻位置出现在 groupby 或者 where 子句中,可以顺序或反序)方式出现在 Projection 的排序列, 任何没有在 groupby 子句出现的必须以单一列等值方式出现在 where 子句中。 SELECT count(a) FROM sortopt WHERE a = 10 GROUP BY b 使用 groupby pipelined,因为 b 处理的所有的 Projection 第 152 页 共 182 页 排序列的列出现在 where 子句等值条件中。 SELECT a FROM sortopt WHERE a = 10 GROUP BY a, b; 使用 groupby pipelined,和前面例子相比即便是多了列 a 仍 然可以使用 groupby pipelined。 SELECT a FROM sortopt WHERE a = 10 GROUP BY b, c; 使用 groupby pipelined, 因为 b 、 c 处理的所有的 Projection 排序列的列出现在 where 子句等值条件中。 SELECT a FROM sortopt WHERE a = 10 GROUP BY c, b; 使用 groupby pipelined, 因为 b 、 c 处理的所有的 Projection 排序列的列出现在 where 子句等值条件中。 SELECT count(a) FROM sortopt WHERE a = 10 GROUP BY c; 使用 groupby hash,因为 c 处理的所有的 Projection 排序 列的列未出现在 where 子句等值条件中。 explain SELECT count(a) FROM sortopt WHERE a = 10 GROUP BY c; Access Path: +-GROUPBY HASH (LOCAL RESEGMENT GROUPS) [Cost: 9, Rows: 2 (NO STATISTICS)] (PATH ID: 1) | Aggregates: count(sortopt.a) | Group By: sortopt.c | Execute on: Query Initiator | +---> STORAGE ACCESS for sortopt [Cost: 8, Rows: 2 (NO STATISTICS)] (PATH ID: 2) | | Projection: public.sortopt_p_node0001 | | Materialize: sortopt.a, sortopt.c | | Filter: (sortopt.a = 10) | | Execute on: Query Initiator explain SELECT count(a) FROM sortopt WHERE a = 10 and b=10 GROUP BY c; Access Path: +-GROUPBY PIPELINED [Cost: 15, Rows: 1 (NO STATISTICS)] (PATH ID: 1) | Aggregates: count(sortopt.a) | Group By: sortopt.c | Execute on: Query Initiator | +---> STORAGE ACCESS for sortopt [Cost: 14, Rows: 1 (NO STATISTICS)] (PATH ID: 2) | | Projection: public.sortopt_p_node0001 | | Materialize: sortopt.a, sortopt.c | | Filter: (sortopt.a = 10) | | Filter: (sortopt.b = 10) | | Execute on: Query Initiator explain SELECT count(a) FROM sortopt WHERE b = 10 GROUP BY c; Access Path: +-GROUPBY HASH (LOCAL RESEGMENT GROUPS) [Cost: 16, Rows: 2 (NO STATISTICS)] (PATH ID: 1) | Aggregates: count(sortopt.a) | Group By: sortopt.c | Execute on: Query Initiator | +---> STORAGE ACCESS for sortopt [Cost: 15, Rows: 2 (NO STATISTICS)] (PATH ID: 2) | | Projection: public.sortopt_p_node0001 第 153 页 共 182 页 | | Materialize: sortopt.a, sortopt.c | | Filter: (sortopt.b = 10) | | Execute on: Query Initiator explain SELECT count(b) FROM sortopt WHERE b = 10 GROUP BY c; Access Path: +-GROUPBY HASH (LOCAL RESEGMENT GROUPS) [Cost: 9, Rows: 2 (NO STATISTICS)] (PATH ID: 1) | Aggregates: count(sortopt.b) | Group By: sortopt.c | Execute on: Query Initiator | +---> STORAGE ACCESS for sortopt [Cost: 8, Rows: 2 (NO STATISTICS)] (PATH ID: 2) | | Projection: public.sortopt_p_node0001 | | Materialize: sortopt.b, sortopt.c | | Filter: (sortopt.b = 10) | | Execute on: Query Initiator explain SELECT count(a),count(b) FROM sortopt WHERE b = 10 GROUP BY c; Access Path: +-GROUPBY HASH (LOCAL RESEGMENT GROUPS) [Cost: 16, Rows: 2 (NO STATISTICS)] (PATH ID: 1) | Aggregates: count(sortopt.a), count(sortopt.b) | Group By: sortopt.c | Execute on: Query Initiator | +---> STORAGE ACCESS for sortopt [Cost: 15, Rows: 2 (NO STATISTICS)] (PATH ID: 2) | | Projection: public.sortopt_p_node0001 | | Materialize: sortopt.b, sortopt.a, sortopt.c | | Filter: (sortopt.b = 10) | | Execute on: Query Initiator 为了使包含 groupby 的查询能够计算出正确的结果,vertica 会保证 groupby 表达式中相同值的所有的行在 相同的节点完成计算,如果 Projection 的设计已经保证了所有的 groupby 子句列已经在节点分段,执行时不要 求重新分段。 为了避免执行时重新分段,groupby 子句必须包含所有 Projection 中的分段的列,而且还可以包含其它的列。 当查询中同时有 groupby 和 joins,关联操作先运算,结果作为 groupby 操作的输入,这些中间结果的分段可能 和查询的 groupby 子句不一致,导致运行时分段。如果不包含 join 关联,则 groupby 子句使用数据库的 Projection 数据处理。 #考虑下面的例子,Projection 按 a、b 分段 CREATE PROJECTION … SEGMENTED BY HASH(a,b) ALL NODES 下表解释是否发生运行时分段 GROUP BY a 需要运行时分段,因为 groupby 未包含所有 Projection 的 分段列 GROUP BY a, b 不需要运行时分段,因为 groupby 包含所有 Projection 的 第 154 页 共 182 页 分段列 GROUP BY a, b, c 不需要运行时分段,因为 groupby 包含所有 Projection 的 分段列 GROUP BY a+1, b 需要运行时分段,因为列 a 包含表达式 #检查是否发生运行时分段,可以通过查看执行计划中是否包含 RESEGMENT GROUPS,类似如下 +-GROUPBY PIPELINED (RESEGMENT GROUPS) [Cost: 194, Rows: 10K (NO STATISTICS)] (PATH ID: 1) +-GROUPBY PIPELINED [Cost: 459, Rows: 10K (NO STATISTICS)] (PATH ID: 1) +-GROUPBY HASH (LOCAL RESEGMENT GROUPS) [Cost: 16, Rows: 2 (NO STATISTICS)] (PATH ID: 1) 10.5.5 优化带 DISTINCT 的查询 对包含 distinct 查询的优化其实和 groupby 类似,因为 vertica 数据库在处理的时候会重写带 distinct 查询 语句为 groupby 查询。 #以下示例使用下面表 CREATE TABLE table1 ( a INT, b INT, c INT ); #示例 1、不使用聚合函数 SELECT DISTINCT a, b, c FROM table1; #上面查询会被重写为如下的 groupby 查询 SELECT a, b, c FROM table1 GROUP BY a, b, c; 关于查询中使用 COUNT (DISTINCT)或其他聚合函数的优化,计算 distinct 聚合比其它的聚合更消耗资源, 如果查询中的 distinct 聚合能够替换成其它往往效率更高,相应的如果查询使用一个 distinct 相比使用多个 distinct 聚合需要较少的资源进行计算,要快很多,而且在内部处理上包含一个 distinct 的聚合和多个 distinct 的聚合也有所不同。 Vertica 允许对数据集进行 COUNT(DISTINCT)计算,如果有合适的 Projection,该计算过程可以使用 GROUPBY PIPELINED 算法优化。有些情况下使用 APPROXIMATE_COUNT_DISTINCT 函数将有更好的性能 表现。 以下情况下 COUNT [Aggregate]性能表现良好:  其中一个排序的 Projection 提供了一个有序的排序聚合  Distinct 值比较少  执行查询需要 hash 聚合 第 155 页 共 182 页 当一个大概的结果就足以满足应用需求的情况下或者计算结果由于数据更新等会滚动的,考虑使用函数 APPROXIMATE_COUNT_DISTINCT,它的结果可能不一定和 COUNT(DISTINCT)完全一样。以下场景可以直 接把 COUNT(DISTINCT)替换为 APPROXIMATE_COUNT_DISTINCT:  有大量的数据集且不要求精确的 distinct 结果  同一个查询中计算多个 distinct count  COUNT(DISTINCT)的执行计划使用 hash 分组 #示例 2、查询有一个 DISTINCT 聚合函数 SELECT a, b, COUNT(DISTINCT c) AS dcnt FROM table1 GROUP BY a, b; 上面的查询会等等价成下面的查询,先去重再分组 SELECT a, b, COUNT(dcnt) FROM (SELECT a, b, c AS dcnt FROM table1 GROUP BY a, b, c) GROUP BY a, b; #示例 3、查询有多个 DISTINCT 聚合函数 以下语句不能非常直接的重写,而且没有办法让 Projection 避免进行 GROUPBY HASH 和数据重新分段,为了 保证正常运行和提升性能需要保证足够的内存,因此处于性能考虑尽可能避免同一个语句中出现多个 DISTINCT 聚合! SELECT a, COUNT(DISTINCT b), COUNT(DISTINCT c) AS dcnt FROM table1 GROUP BY a; 10.5.6 优化关联查询 当查询涉及的表超过一个时,vertica 需要进行以下至少一个操作,以完成关联动作,对数据排序;对数据进 行分段。Vertica 使用了两种算法的 join 方式,分别是 hash join 和 merge join。 Merge join:如果数据是事先排序的,使用 merge join 消耗更少内存,效率更高。Vertica 只能对有 select 或 insert 的查询使用 merge join。 Hash join:使用这种方式时 vertica 使用小表做内层表,在内存中创建关联列的 hash 表,vertica 扫描外 层表或大表的数据,并探测 hash 表是否匹配。Hash join 不需要数据事先排序,但是需要消耗更多的内存。如 果 hash 表的数据都能够放入内存,则 hash join 的代价会降低,因为不需要往磁盘交换数据。优化器会自动选 择 hash join 当 Projection 没有在关联列排序时。 为了让 vertica 能够使用 merge join,对 Projection 的设计时让关联列出现在排序的首列中。如果关联列是 Projection 的第二列且首列出现在等值谓词中。否则,要使用 merge join,先通过子查询对关联列进行排序再进 行关联。 #示例 1、Projection 按关联列排序,所以查询会使用 merge join CREATE TABLE first ( data INT, join_key INT 第 156 页 共 182 页 ); CREATE TABLE second ( data INT, join_key INT ); CREATE PROJECTION first_p (data, join_key) AS SELECT data, join_key FROM first ORDER BY join_key; CREATE PROJECTION second_p (data, join_key) AS SELECT data, join_key FROM second ORDER BY join_key; SELECT first.data, second.data FROM first, second WHERE first.join_key = second.join_key; #示例 2、关联列是 Projection 的第二排序列,第一列出现在谓词的等值条件中,查询也会使用 merge join CREATE TABLE first ( data INT, join_key INT ); CREATE TABLE second ( data INT, join_key INT ); CREATE PROJECTION first_p (data, join_key) AS SELECT data, join_key FROM first ORDER BY data, join_key; CREATE PROJECTION second_p (data, join_key) AS SELECT data, join_key FROM second ORDER BY join_key; SELECT first.data, second.data FROM first, second WHERE first.join_key = second.join_key AND first.data = 5; #示例 3、如果出现在等值谓词左边的是关联的一个表,右边是关联的另外一个表性能优化 如下第一个查询比第二个查询性能优化,因为第二个需要更多的计算 SELECT * FROM T JOIN X WHERE T.a - T.b = X.x1; VS SELECT * FROM T JOIN X WHERE T.a = X.x1 + T.b 为了使得 join 的效率得到优化,要检查 vertica 是否总是选择了大表作外层表(关联的左边),小表作内层 表。为了提升多表关联的效率,创建 Projection 让其能够在关联键上相等的分段,这种 Projection 叫作 ISPS (identically-segmented projections)。ISPS 允许关联只在每个节点本地上操作数据,不需要跨节点移动数 据。 第 157 页 共 182 页 判断 Projection 是否在查询的关联键上相等分段的,通过使用 EXPLAIN 命令,检查输出是否包含 RESEGMENT 或者 BROADCAST,如果包含则不是相等分段的。 Vertica 优化器选择一个 Projection 为查询的所有表提供数据,如果选中的两个用来关联的 Projection 都是 分段的,优化器使用分段表达式和查询的关联表达式来验证数据是否能够在不进行数据移动的情况下进行关联。 对于 ISPs 的满足条件考虑以下的例子:Projection 的所有分段的列是参与关联列的子集,下面的情况必须 成立 t1 表的 Projection p1 和 t2 表的 Projection p2 都在关联列分段:  关联条件必须符合下面的公式:t1.j1 = t2.j1 AND t1.j2 = t2.j2 AND ... t1.jN = t2.jN。  关联列的数据类型必须相同,但是长度并不一定相同,如 t1.j1 :CHAR(10),t2.j1 可以使任 何 char 或 varchar,但不能使 INTEGER。  如果 p1 在{t1.s1, t1.s2, ... t1.sN}列分段,那么这些列都必须是关联列,相应的 p2 也要类似  p1 和 p2 分段表达式必须结构性等价,如 p1 SEGMENTED BY hash(t1.x)和 p2 SEGMENTED BY hash(t2.x)是结构性等价的,而 p1 SEGMENTED BY hash(t1.x)和 p2 SEGMENTED BY hash(t2.x+1)不是结构性等价的。  p1 和 p2 必须有相同的分段数  分段数据的节点分配必须匹配,如使用 offset 子句,那么 p1 and p2 的 OFFSET 必须匹配  如果 vertica 发现 t1 和 t2 未相等分段,必要时数据会通过网络跨节点重新分布 提示:对可能出现关联的表创建分段的 Projection #创建两个表指定 ISP 条件 CREATE TABLE t1 (id INT, x1 INT, y1 INT) SEGMENTED BY HASH(id) ALL NODES; CREATE TABLE t2 (id INT, x2 INT, y2 INT) SEGMENTED BY HASH(id) ALL NODES; #判断以下关联是否符合 ISP SELECT * FROM t1 JOIN t2 ON t1.id = t2.id; -- ISP SELECT * FROM t1 JOIN t2 ON t1.id = t2.id AND t1.x1 = t2.x2; -- ISP SELECT * FROM t1 JOIN t2 ON t1.x1 = t2.x2; -- NOT ISP SELECT * FROM t1 JOIN t2 ON t1.id = t2.x2; -- NOT ISP #验证以上判断 explain SELECT * FROM t1 JOIN t2 ON t1.x1 = t2.x2; Access Path: +-JOIN HASH [Cost: 13, Rows: 1 (NO STATISTICS)] (PATH ID: 1) Inner (BROADCAST) | Join Cond: (t1.x1 = t2.x2) | Materialize at Output: t1.id, t1.y1 | Execute on: All Nodes 第 158 页 共 182 页 | +-- Outer -> STORAGE ACCESS for t1 [Cost: 6, Rows: 5 (NO STATISTICS)] (PATH ID: 2) | | Projection: public.t1_b0 | | Materialize: t1.x1 | | Execute on: All Nodes | | Runtime Filter: (SIP1(HashJoin): t1.x1) | +-- Inner -> STORAGE ACCESS for t2 [Cost: 5, Rows: 2 (NO STATISTICS)] (PATH ID: 3) | | Projection: public.t2_b0 | | Materialize: t2.id, t2.x2, t2.y2 | | Execute on: All Nodes explain SELECT * FROM t1 JOIN t2 ON t1.id = t2.x2; Access Path: +-JOIN HASH [Cost: 21, Rows: 1 (NO STATISTICS)] (PATH ID: 1) Inner (RESEGMENT) | Join Cond: (t1.id = t2.x2) | Materialize at Output: t1.x1, t1.y1 | Execute on: All Nodes | +-- Outer -> STORAGE ACCESS for t1 [Cost: 6, Rows: 5 (NO STATISTICS)] (PATH ID: 2) | | Projection: public.t1_b0 | | Materialize: t1.id | | Execute on: All Nodes | | Runtime Filter: (SIP1(HashJoin): t1.id) | +-- Inner -> STORAGE ACCESS for t2 [Cost: 13, Rows: 4 (NO STATISTICS)] (PATH ID: 3) | | Projection: public.t2_b0 | | Materialize: t2.id, t2.x2, t2.y2 | | Execute on: All Nodes 如果 A 和 B 是相等分段的 Projection,他们的 buddy Projection Abuddy 和 Bbuddy 也应该是对应相等分段的。 CREATE PROJECTION t1_b1 (id, x1, y1) AS SELECT * FROM t1 SEGMENTED BY HASH(id) ALL NODES OFFSET 1; CREATE PROJECTION t2_b1 (id, x2, y2) AS SELECT * FROM t2 SEGMENTED BY HASH(id) ALL NODES OFFSET 2; 不是相等分段的,因为 offset 不同 CREATE PROJECTION t1_b2 (id, x1, y1) AS SELECT * FROM t1 SEGMENTED BY HASH(id, x1) ALL NODES OFFSET 1; CREATE PROJECTION t2_b2 (id, x2, y2) AS SELECT * FROM t2 SEGMENTED BY HASH(id) ALL NODES OFFSET 2; 不是相等分段的,因为分段 表达式不同 10.5.7 优化 ORDER BY 查询 如果查询的 order by 子句和 Projection 的 order by 子句相同的话,性能比较好。考虑下面曾经在 group 第 159 页 共 182 页 by 优化的时候使用的例子 #表 sortopt 有四列,Projection sortopt_p 按 a、b、c 排序 CREATE TABLE sortopt ( a INT NOT NULL, b INT NOT NULL, c INT, d INT ); CREATE PROJECTION sortopt_p ( a_proj, b_proj, c_proj, d_proj ) AS SELECT * FROM sortopt ORDER BY a,b,c UNSEGMENTED ALL NODES; INSERT INTO sortopt VALUES(5,2,13,84); INSERT INTO sortopt VALUES(14,22,8,115); INSERT INTO sortopt VALUES(79,9,401,33); #查询包含以下 order by 子句可以不必重新排序 ORDER BY a 、ORDER BY a, b 、ORDER BY a, b, c 但是下面查询需要重新排序,因为创建 Projection 时不能指定排序方式,物理存储上只能是 asc 方式 SELECT * FROM sortopt ORDER BY a DESC, b, c; 10.5.8 优化 SQL-99 分析函数 分析函数和聚合函数有所不同,聚合函数的结果一般只能有一个,分析函数结果可以有多个。函数 OVER()可 以不需要窗口子句,如果查询中使用 SUM(x)和空的 over()子句,分析函数会当成报告函数,把所有输入当成一个 分区,对每一行的值聚合出一个结果,并且查询只在一个节点允许。 如果添加 PARTITION BY 子句,查询在多节点允许,性能会得到提升,因此应尽量避免只在一个节点执行的情 况。另外 over()函数必须跟随分析函数使用,不能单独使用。 #以下示例帮助理解 over()函数 dbadmin=> create table test(sales_id varchar2(2),sales varchar2(10),dest varchar2(10),dept varchar2(16),revenue number); CREATE TABLE Time: First fetch (0 rows): 42.898 ms. All rows formatted: 42.939 ms dbadmin=> dbadmin=> dbadmin=> insert into test values('11','smith','hangzhou','market',1000); insert into test values('12','smith','wenzhou','market',2000); insert into test values('13','allen','wenzhou','channels',3000); insert into test values('14','allen','wenzhou','channels',4000); 第 160 页 共 182 页 insert into test values('15','jekch','shanghai','channels',2500); insert into test values('11','smith','hangzhou','market',1000); insert into test values('12','smith','wenzhou','market',2000); OUTPUT -------- 1 (1 row) Time: First fetch (1 row): 596.067 ms. All rows formatted: 596.099 ms dbadmin=> insert into test values('12','smith','wenzhou','market',2000); OUTPUT -------- 1 (1 row) Time: First fetch (1 row): 281.522 ms. All rows formatted: 281.573 ms dbadmin=> insert into test values('13','allen','wenzhou','channels',3000); OUTPUT -------- 1 (1 row) Time: First fetch (1 row): 78.413 ms. All rows formatted: 78.447 ms dbadmin=> insert into test values('14','allen','wenzhou','channels',4000); OUTPUT -------- 1 (1 row) Time: First fetch (1 row): 259.187 ms. All rows formatted: 259.248 ms dbadmin=> insert into test values('15','jekch','shanghai','channels',2500); OUTPUT -------- 1 (1 row) Time: First fetch (1 row): 298.178 ms. All rows formatted: 298.198 ms dbadmin=> insert into test values('11','smith','hangzhou','market',1000); OUTPUT -------- 1 (1 row) Time: First fetch (1 row): 265.984 ms. All rows formatted: 266.044 ms dbadmin=> insert into test values('12','smith','wenzhou','market',2000); OUTPUT -------- 1 (1 row) Time: First fetch (1 row): 302.209 ms. All rows formatted: 302.270 ms dbadmin=> commit; 第 161 页 共 182 页 COMMIT Time: First fetch (0 rows): 24.673 ms. All rows formatted: 24.700 ms dbadmin=> #按销售人员名递加汇总 revenue dbadmin=> select sales_id,sales,revenue,sum(revenue)over(order by sales)递加销售总额 from test; sales_id | sales | revenue | 递加销售总额 ----------+-------+---------+-------------- 13 | allen | 3000 | 7000 14 | allen | 4000 | 7000 15 | jekch | 2500 | 9500 12 | smith | 2000 | 15500 12 | smith | 2000 | 15500 11 | smith | 1000 | 15500 11 | smith | 1000 | 15500 (7 rows) Time: First fetch (7 rows): 4136.503 ms. All rows formatted: 4136.667 ms #按销售人员 ID 递加汇总 revenue dbadmin=> select sales_id,sales,revenue,sum(revenue)over(order by sales_id)递加销售总额 from test; sales_id | sales | revenue | 递加销售总额 ----------+-------+---------+-------------- 11 | smith | 1000 | 2000 11 | smith | 1000 | 2000 12 | smith | 2000 | 6000 12 | smith | 2000 | 6000 13 | allen | 3000 | 9000 14 | allen | 4000 | 13000 15 | jekch | 2500 | 15500 (7 rows) Time: First fetch (7 rows): 261.130 ms. All rows formatted: 261.187 ms #按销售人员 ID 分组汇总 revenue dbadmin=> select sales_id,sales,revenue,sum(revenue)over(partition by sales_id) 分组销售总额 from test; sales_id | sales | revenue | 分组销售总额 ----------+-------+---------+-------------- 13 | allen | 3000 | 3000 14 | allen | 4000 | 4000 11 | smith | 1000 | 2000 11 | smith | 1000 | 2000 12 | smith | 2000 | 4000 12 | smith | 2000 | 4000 15 | jekch | 2500 | 2500 (7 rows) Time: First fetch (7 rows): 219.791 ms. All rows formatted: 219.904 ms dbadmin=> select sales_id,sales,revenue,sum(revenue)over(partition by sales) 分组销售总额 from test; sales_id | sales | revenue | 分组销售总额 第 162 页 共 182 页 ----------+-------+---------+-------------- 13 | allen | 3000 | 7000 14 | allen | 4000 | 7000 15 | jekch | 2500 | 2500 11 | smith | 1000 | 6000 12 | smith | 2000 | 6000 12 | smith | 2000 | 6000 11 | smith | 1000 | 6000 (7 rows) Time: First fetch (7 rows): 304.826 ms. All rows formatted: 304.918 ms dbadmin=> select sales_id,sales,revenue,sum(revenue)over(partition by sales order by sales_id) 分组递加销售总额 from test; sales_id | sales | revenue | 分组递加销售总额 ----------+-------+---------+------------------ 15 | jekch | 2500 | 2500 11 | smith | 1000 | 2000 11 | smith | 1000 | 2000 12 | smith | 2000 | 6000 12 | smith | 2000 | 6000 13 | allen | 3000 | 3000 14 | allen | 4000 | 7000 (7 rows) Time: First fetch (7 rows): 126.425 ms. All rows formatted: 126.472 ms dbadmin=> select sales_id,sales,revenue,sum(revenue)over(partition by sales_id order by sales) 分组递加销售总额 from test; sales_id | sales | revenue | 分组递加销售总额 ----------+-------+---------+------------------ 13 | allen | 3000 | 3000 14 | allen | 4000 | 4000 11 | smith | 1000 | 2000 11 | smith | 1000 | 2000 12 | smith | 2000 | 4000 12 | smith | 2000 | 4000 15 | jekch | 2500 | 2500 (7 rows) Time: First fetch (7 rows): 93.305 ms. All rows formatted: 93.352 ms dbadmin=> select sales_id,sales,count(*)over()求总计数,count(*)over(order by sales_id)递加求计数,count(*)over(partition by sales_id)分组求计数,count(*)over(partition by sales_id order by sales)分组递加求计数 from test; sales_id | sales | 求总计数 | 递加求计数 | 分组求计数 | 分组递加求计数 ----------+-------+----------+------------+------------+---------------- 13 | allen | 7 | 5 | 1 | 1 14 | allen | 7 | 6 | 1 | 1 11 | smith | 7 | 2 | 2 | 2 11 | smith | 7 | 2 | 2 | 2 12 | smith | 7 | 4 | 2 | 2 12 | smith | 7 | 4 | 2 | 2 第 163 页 共 182 页 15 | jekch | 7 | 7 | 1 | 1 (7 rows) Time: First fetch (7 rows): 384.952 ms. All rows formatted: 385.021 ms 默认情况下 Projection 的排序时按升序进行的,但是 NULL 的存放却依赖于列的数据类型。分析函数 over ()中的 order by 子句和查询语句总的 order by 子句语义上是有所不同的,见下表。 分析函数的 order by 子句对数据的排序是基于分析函数的结 果,排序可以指定升序或降序,同时可以指定 NULL 值存储在排 序数据的前面(NULLS FIRST)或后面(NULLS LAST)。 如果排序是 ASC,NULL 值存放在排序数据的后面,即 NULLS LAST;如果排序是 DESC,NULL 值存放在排序数据的前面,即 NULLS FIRST。 SQL 语句的 order by 子句只能指定升序或降序。 Vertica 中对于 NUMERIC, INTEGER, DATE, TIME, TIMESTAMP, and INTERVAL 类型数据是 NULLS FIRST 的,即 NULL 值 出 现 在 排 序 Projection 的 前 面 ; 对 于 FLOAT , STRING, and BOOLEAN 类型的数据是 NULLS LAST 的。 如果不关心 NULL 值的存放位置,或者清楚知道分析函数中没有 NULL 值,可以指定为 NULLS AUTO,不管是 什么数据类型,vertica 自己判断选择哪种方式并以最快速度运行。当然也可以指定为 NULLS FIRST or NULLS LAST 因此需要精心的规划我们的查询,以减少数据排序和取得最优的运行效果。考虑下面的例子: #NULL 存放排序示例 dbadmin=> CREATE TABLE tt ( dbadmin(> x FLOAT, dbadmin(> y FLOAT ); CREATE TABLE dbadmin=> CREATE PROJECTION tt_p (x, y) AS SELECT * FROM tt dbadmin-> ORDER BY x, y UNSEGMENTED ALL NODES; CREATE PROJECTION dbadmin=> SELECT x, RANK() OVER (ORDER BY x) FROM tt; x | ?column? ---+---------- (0 rows) dbadmin=> insert into tt values(1.1,-2.2); OUTPUT -------- 1 (1 row) dbadmin=> insert into tt values(18.9,-22.7); OUTPUT -------- 1 (1 row) dbadmin=> insert into tt values(11.4,20.5); OUTPUT -------- 1 (1 row) 第 164 页 共 182 页 dbadmin=> commit; COMMIT #上面查询由于 X 列是 float 类型,和默认的排序 ASC+NULLS LAST 匹配,因此可以消除排序操作,运行会比 较快,然而如果 X 列的数据类型为 INTEGER,则其对应的 NULL 排序为(NULLS FIRST),和分析函数 ASC 对应 NULL LAST 不匹配,所以数据需要重新排序 #使用以下查询可以消除数据的重新排序 SELECT x, RANK() OVER (ORDER BY x NULLS FIRST) FROM t; #当然也可以 SELECT x, RANK() OVER (ORDER BY x NULLS AUTO) FROM t; 小心的书写查询语句和精心设计 Projection,可以帮助优化器减少执行分析函数时进行不必要的 NULL 排序, 提升性能。 如为了避免查询 employee 出现不必要的对 Projection 的重新排序,定义 Projection 的排序列不允许 NULL 值。 dbadmin=> CREATE TABLE employee dbadmin-> (empno INT, dbadmin(> deptno INT NOT NULL, dbadmin(> sal INT NOT NULL); CREATE PROJECTION employee_p AS SELECT * FROM employee ORDER BY deptno, sal;CREATE TABLE dbadmin=> CREATE PROJECTION employee_p AS dbadmin-> SELECT * FROM employee dbadmin-> ORDER BY deptno, sal; CREATE PROJECTION dbadmin=> INSERT INTO employee VALUES(101,10,50000); INSERT INTO employee VALUES(104,10,45000); INSERT INTO employee VALUES(105,20,97000); INSERT INTO employee VALUES(108,20,33000); INSERT INTO employee VALUES(109,20,51000); OUTPUT -------- 1 (1 row) dbadmin=> INSERT INTO employee VALUES(103,10,43000); OUTPUT -------- 第 165 页 共 182 页 1 (1 row) dbadmin=> INSERT INTO employee VALUES(104,10,45000); OUTPUT -------- 1 (1 row) dbadmin=> INSERT INTO employee VALUES(105,20,97000); OUTPUT -------- 1 (1 row) dbadmin=> INSERT INTO employee VALUES(108,20,33000); OUTPUT -------- 1 (1 row) dbadmin=> INSERT INTO employee VALUES(109,20,51000); OUTPUT -------- 1 (1 row) dbadmin=> SELECT * FROM employee; empno | deptno | sal -------+--------+------- 103 | 10 | 43000 104 | 10 | 45000 101 | 10 | 50000 108 | 20 | 33000 109 | 20 | 51000 105 | 20 | 97000 (6 rows) dbadmin=> SELECT deptno, sal, empno, RANK() OVER (PARTITION BY deptno ORDER BY sal) FROM employee; deptno | sal | empno | ?column? --------+-------+-------+---------- 10 | 43000 | 103 | 1 10 | 45000 | 104 | 2 10 | 50000 | 101 | 3 20 | 33000 | 108 | 1 第 166 页 共 182 页 20 | 51000 | 109 | 2 20 | 97000 | 105 | 3 (6 rows) 10.5.9 优化 LIMIT 查询 带 order by 的 limit 子句和使用 vertica 分析函数 ROW_NUMBER()只返回一部分结果集的查询,vertica 处理 这类查询使用一种叫作 Top-K 的优化机制,它其实是通过数据库查询进行分类的处理过程。Top-K 优化机制避 免对所有数据集进行排序以取得小部分结果,这样可以显著提升性能。 #如下查询只查询最小的三个记录并排序 SELECT * FROM t1 ORDER BY x LIMIT 3; 由于这种机制,limit 子句不指定 order by 时查询结果可能是不确定的。 查询中包含 OVER(ORDER BY)子句谓词中包含 ROW_NUMBER 的语句可以通过 Top-K 优化机制得到优化。但是当 ROW_NUMBER()使用了 partition by 子句时不能通过 limit 转换。 #如下查询等效于后面的查询 SELECT x FROM (SELECT *, ROW_NUMBER() OVER (ORDER BY x) AS row FROM t1) t2 WHERE row <= 3; == SELECT ROW_NUMBER() OVER (ORDER BY x) AS RANK FROM t1 LIMIT 3; 10.5.10 优化 INSERT-SELECT 语句 如 INSERT-SELECT 查询中 SELECT 子句包含关联,vertica 会判断 select 部分是使用 hash join 或者 merge join。当需要插入的 Projection 已经排序时,INSERT-SELECT 查询必须进行一个 merge jion 关联,而即将处理的 数据未事先排序时,select 部分的一个合适的 order by 子句能够促进使用 merge join 的使用。 因此,进行 INSERT-SELECT 时为了避免 INSERT 操作的排序,应使 select 的排序和目标表的 Projection 的排 序相一致。 #考虑下面的例子 CREATE TABLE source (col1 INT, col2 INT, col3 INT); CREATE PROJECTION source_p (col1, col2, col3) AS SELECT col1, col2, col3 FROM source ORDER BY col1, col2, col3 SEGMENTED BY HASH(col3) ALL NODES; CREATE TABLE destination (col1 INT, col2 INT, col3 INT); CREATE PROJECTION destination_p (col1, col2, col3) 第 167 页 共 182 页 AS SELECT col1, col2, col3 FROM destination ORDER BY col1, col2, col3 SEGMENTED BY HASH(col3) ALL NODES; #下面的例子不需 insert 排序,因为源表查询结果已按目标表的 Projection 排序 INSERT /*+direct*/ INTO destination SELECT * FROM source; #下面的例子需要 insert 排序 INSERT /*+direct*/ INTO destination SELECT col1, col3, col2 FROM source; #下面的例子不需要 insert 排序,因为 SELECT 列和目标表的 Projection 排序列虽然不 match,但是 order by 子句让查询结果重新排序了 INSERT /*+direct*/ INTO destination SELECT col1, col3, col2 FROM source GROUP BY col1, col3, col2 ORDER BY col1, col2, col3 ; 如果 INSERT-SELECT 的源表和目标表都已进行分段,那么让源表和目标表都在相同的列进行分段,以避免插 入操作需要额外进行重新分段。 #如下源表和目标表都在 col3 分段 CREATE TABLE source (col1 INT, col2 INT, col3 INT); CREATE PROJECTION source_p (col1, col2, col3) AS SELECT col1, col2, col3 FROM source SEGMENTED BY HASH(col3) ALL NODES; CREATE TABLE destination (col1 INT, col2 INT, col3 INT); CREATE PROJECTION destination_p (col1, col2, col3) AS SELECT col1, col2, col3 FROM destination SEGMENTED BY HASH(col3) ALL NODES; INSERT /*+direct*/ INTO destination SELECT * FROM source; 10.5.11 优化更新和删除操作 首先 vertica 系统内部的设计都是主要基于查询密集的工作负载,因此 DELETE and UPDATE 可能无法获得像查 询类似的效果。DELETE 和 UPDATE 要更新所有相关的 Projection,所以速度受限于最慢的 Projection。提高 DELETE 和 UPDATE 的性能,请考虑以下方面:  大量删除后的查询性能-进行大量数据删除,在未清空之前查询性能可能受到拖累。查询过程中要 排除已删除数据,需要进行额外的处理,性能必然受到拖累,但是变慢的程度可能因表定义、数 据大小、查询而异。如果删除了表里大量的数据,请考虑清空已删除数据,清空方法是使用手动 第 168 页 共 182 页 清空或者设置合适的清空策略:SELECT SET_CONFIG_PARAMETER('HistoryRetentionTime', '{ | -1 }' );  Recover 性能-系统出现节点 crash 之后,为了保证 ksafe 数据恢复时必须进行的,大量删除数 据会导致恢复速度变慢。  并发-对表的删除和更新需要独占锁,同一时间只能有一个删除或更新操作,且同时不能有插入操 作。  Pre-join projections-避免对纬度表的经常更新,对 pre-join projections 的大量删除和更新 会级联到基表上,造成大量的删除和更新操作。 删除和更新优化的过程基表是类似的,后面会给出一些简单的步骤优化删除和更新的效率。 对于可能经常进行大数据量删除的表,考虑使用分区表,分区表通过删除分区提供最优的删除效率。 当所有删除和更新的谓词列都出现在 Projection 中时,Projection 就是删除和更新优化的。单独的 Projection 或 pro-join Projection 都可以进行该优化。 #考虑下面的例子: CREATE TABLE t (a INTEGER, b INTEGER, c INTEGER); CREATE PROJECTION p1 (a, b, c) AS SELECT * FROM t ORDER BY a; CREATE PROJECTION p2 (a, c) AS SELECT a, c FROM t ORDER BY c, a; #下面删除查询 p1、p2 适合删除优化 DELETE from t WHERE a = 1; #下面删除查询 p1 适合删除优化,因为 p2 未出现 b 列 DELETE from t WHERE b = 1; 所有删除和更新的谓词列都必须出现在 Projection 的定义中时,才能进行删除优化。 CREATE TABLE tb1 (a INT, b INT, c INT, d INT); CREATE TABLE tb2 (g INT, h INT, i INT, j INT); CREATE PROJECTION tb1_p AS SELECT a, b, c, d FROM tb1 ORDER BY a; CREATE PROJECTION tb1_p_2 AS SELECT a FROM tb1 ORDER BY a; CREATE PROJECTION tb2_p AS SELECT g, h, i, j FROM tb2 ORDER BY i; #tb1 表的两个 Projection 都包含 a 列,所以都可以适合删除优化 DELETE FROM tb1 WHERE tb1.a IN (SELECT tb2.i FROM tb2); 第 169 页 共 182 页 对于进行删除和更新的表,设计 Projection 让删除和更新谓词列都出现在 Projection 的排序列中。 另外删除优化有以下几个方面的限制:  pre-join projections 的节点宕机  子查询中参考了使用了 replicated and pre-join projections 的源表 DELETE FROM tb1 WHERE tb1.a IN (SELECT e FROM tb2, tb2 WHERE tb2.e = tb1.e);  使用的子查询不返回多行记录,如 DELETE FROM tb1 WHERE tb1.a = (SELECT k from tb2); 以下是手动清空数据的过程:  决定那个时间点的数据需要进行 purge  使用下面方法之一设置 AHM 到那个时间点:SET_AHM_TIME()、SET_AHM_EPOCH()、 MAKE_AHM_NOW()(该方法清空所有删除数据)。SET_AHM_TIME or GET_AHM_TIME 对应的时间戳是和 epoch 对应的,是以三分钟为粒度的,就是说可能有三分钟的误差。  手动执行 PURGE_PROJECTION()或 PURGE_TABLE()或 PURGE()  使用 TM 的 mergeout 操作清空删除数据 11. 常见问题处理 11.1 数据库的后台进程被 kill 一般情况下 Vertica 有多个后台进程 agent.sh、simply_fast.py、spread、vertica、vertica-udx-zygote, 除了 vertica-udx-zygote 以外 kill 其它进程会导致本节点的数据库 crash。 #检查正常状态下 vertica 进程 [dbadmin@V3 ~]$ ps -ef|grep vertica dbadmin 5831 1 0 11:51 ? 00:00:00 /bin/bash /opt/vertica/agent/agent.sh /opt/vertica/config/users/dbadmin/agent.conf dbadmin 5838 5831 0 11:51 ? 00:00:06 /opt/vertica/oss/python/bin/python ./simply_fast.py dbadmin 6267 1 0 11:59 ? 00:00:14 /opt/vertica/spread/sbin/spread -c /home/dbadmin/catalog/vertica/v_vertica_node0003_catalog/spread.conf dbadmin 6269 1 1 11:59 ? 00:03:19 /opt/vertica/bin/vertica -D /home/dbadmin/catalog/vertica/v_vertica_node0003_catalog -C vertica -n v_vertica_node0003 -h 10.75.7.112 -p 5433 -P 第 170 页 共 182 页 4803 dbadmin 6272 6269 0 11:59 ? 00:00:05 /opt/vertica/bin/vertica-udx-zygote 12 10 6269 debug-log-off /home/dbadmin/catalog/vertica/v_vertica_node0003_catalog/UDxLogs dbadmin 9541 9449 0 14:52 pts/2 00:00:00 grep vertica #kill 掉某些后台进程 [dbadmin@V3 ~]$ kill -9 6272 #监控 vertica 数据库的状态 [dbadmin@V3 ~]$ admintools -t view_cluster DB | Host | State ---------+-------------+------- vertica | ALL | UP #通过以下 sql 语句可以看到 vertica 的恢复状态 select node_name, recover_epoch, recovery_phase, current_completed, is_running from recovery_status; select node_name, status , progress from projection_recoveries; 11.2 数据文件被删除 删除 vertica 数据库文件,vertica 实例很快就会 down 掉,此时节点可能无法再次启动,如果删除 catalog 文件再启动则节点自动重建,或者可以使用-F 强制节点启动,此时节点需要从正常接 recover 直到正常。 11.2.1 删除 1 个节点数据文件 #删除节点的 data 文件后直接重启节点失败 [dbadmin@V3 data]$ admintools -t restart_node -d vertica -s 10.75.7.112 -p 123456 *** Restarting nodes for database vertica *** restart host 10.75.7.112 with catalog v_vertica_node0003_catalog issuing multi-node restart Starting nodes: v_vertica_node0003 (10.75.7.112) Starting Vertica on all nodes. Please wait, databases with large catalogs may take a while to initialize. Node Status: v_vertica_node0003: (DOWN) Node Status: v_vertica_node0003: (DOWN) Node Status: v_vertica_node0003: (DOWN) Node Status: v_vertica_node0003: (DOWN) Node Status: v_vertica_node0003: (DOWN) Node Status: v_vertica_node0003: (DOWN) Node Status: v_vertica_node0003: (DOWN) Node Status: v_vertica_node0003: (DOWN) Node Status: v_vertica_node0003: (DOWN) Node Status: v_vertica_node0003: (DOWN) Restart Nodes result: 2 第 171 页 共 182 页 #使用-F 强制启动,此时失败节点会经历,重新初始化、从正常节点恢复、恢复完成的过程 [dbadmin@V3 data]$ admintools -t restart_node -d vertica -s 10.75.7.112 -p 123456 -F *** Restarting nodes for database vertica *** restart host 10.75.7.112 with catalog v_vertica_node0003_catalog issuing multi-node restart Starting nodes: v_vertica_node0003 (10.75.7.112) Starting Vertica on all nodes. Please wait, databases with large catalogs may take a while to initialize. Node Status: v_vertica_node0003: (INITIALIZING) Node Status: v_vertica_node0003: (RECOVERING) Node Status: v_vertica_node0003: (RECOVERING) Node Status: v_vertica_node0003: (RECOVERING) Node Status: v_vertica_node0003: (RECOVERING) Node Status: v_vertica_node0003: (RECOVERING) Node Status: v_vertica_node0003: (RECOVERING) Node Status: v_vertica_node0003: (UP) Restart Nodes result: 1 #从存活节点可以观察到该过程 [dbadmin@V1 ~]$ admintools -t view_cluster DB | Host | State ---------+-------------+-------------- vertica | 10.75.7.110 | UP vertica | 10.75.7.111 | UP vertica | 10.75.7.112 | INITIALIZING [dbadmin@V1 ~]$ admintools -t view_cluster DB | Host | State ---------+-------------+------------ vertica | 10.75.7.110 | UP vertica | 10.75.7.111 | UP vertica | 10.75.7.112 | RECOVERING [dbadmin@V1 ~]$ admintools -t view_cluster DB | Host | State ---------+-------------+------------ vertica | 10.75.7.110 | UP vertica | 10.75.7.111 | UP vertica | 10.75.7.112 | RECOVERING [dbadmin@V1 ~]$ admintools -t view_cluster DB | Host | State ---------+------+------- vertica | ALL | UP 第 172 页 共 182 页 11.2.2 删除 2 个节点数据文件 超过 ksafe 且超过集群一半的节点数据文件被删除时,数据必然出现丢失,数据库无法启动,必须从备份恢复。 #删除两个节点的 data 数据,此时超过 ksafe 且超过一半,数据库 down [dbadmin@V1 ~]$ admintools -t start_db -d vertica -p 123456 Starting nodes: v_vertica_node0003 (10.75.7.112) v_vertica_node0001 (10.75.7.110) v_vertica_node0002 (10.75.7.111) Starting Vertica on all nodes. Please wait, databases with large catalogs may take a while to initialize. Node Status: v_vertica_node0001: (INITIALIZING) v_vertica_node0002: (DOWN) v_vertica_node0003: (DOWN) Node Status: v_vertica_node0001: (INITIALIZING) v_vertica_node0002: (DOWN) v_vertica_node0003: (DOWN) Node Status: v_vertica_node0001: (INITIALIZING) v_vertica_node0002: (DOWN) v_vertica_node0003: (DOWN) Node Status: v_vertica_node0001: (INITIALIZING) v_vertica_node0002: (DOWN) v_vertica_node0003: (DOWN) Node Status: v_vertica_node0001: (INITIALIZING) v_vertica_node0002: (DOWN) v_vertica_node0003: (DOWN) Node Status: v_vertica_node0001: (INITIALIZING) v_vertica_node0002: (DOWN) v_vertica_node0003: (DOWN) Node Status: v_vertica_node0001: (INITIALIZING) v_vertica_node0002: (DOWN) v_vertica_node0003: (DOWN) Node Status: v_vertica_node0001: (INITIALIZING) v_vertica_node0002: (DOWN) v_vertica_node0003: (DOWN) Node Status: v_vertica_node0001: (INITIALIZING) v_vertica_node0002: (DOWN) v_vertica_node0003: (DOWN) Node Status: v_vertica_node0001: (INITIALIZING) v_vertica_node0002: (DOWN) v_vertica_node0003: (DOWN) Nodes DOWN: v_vertica_node0002, v_vertica_node0003, v_vertica_node0001 (may be still initializing). It is suggested that you continue waiting. Do you want to continue waiting? (yes/no) [yes] Node Status: v_vertica_node0001: (INITIALIZING) v_vertica_node0002: (DOWN) v_vertica_node0003: (DOWN) Node Status: v_vertica_node0001: (INITIALIZING) v_vertica_node0002: (DOWN) v_vertica_node0003: (DOWN) Node Status: v_vertica_node0001: (INITIALIZING) v_vertica_node0002: (DOWN) v_vertica_node0003: (DOWN) Node Status: v_vertica_node0001: (INITIALIZING) v_vertica_node0002: (DOWN) v_vertica_node0003: (DOWN) Node Status: v_vertica_node0001: (INITIALIZING) v_vertica_node0002: (DOWN) v_vertica_node0003: (DOWN) Node Status: v_vertica_node0001: (INITIALIZING) v_vertica_node0002: (DOWN) v_vertica_node0003: (DOWN) Node Status: v_vertica_node0001: (INITIALIZING) v_vertica_node0002: (DOWN) v_vertica_node0003: (DOWN) Node Status: v_vertica_node0001: (INITIALIZING) v_vertica_node0002: (DOWN) v_vertica_node0003: (DOWN) Node Status: v_vertica_node0001: (INITIALIZING) v_vertica_node0002: (DOWN) v_vertica_node0003: (DOWN) Node Status: v_vertica_node0001: (INITIALIZING) v_vertica_node0002: (DOWN) v_vertica_node0003: (DOWN) Nodes DOWN: v_vertica_node0002, v_vertica_node0003, v_vertica_node0001 (may be still initializing). It is suggested that you continue waiting. Do you want to continue waiting? (yes/no) [yes] no Database startup successful, but it may be incomplete. Some nodes remain in a transitional state. Waiting can sometimes resolve this problem. See Database Cluster State in Main Menu for updated cluster state. If this state persists, try using the Advanced menu to Stop Vertica on Host, then Restart Database. Press RETURN to continue Database vertica did not start successfully #启动失败,强制启动也失败,因为数据已经丢失 [dbadmin@V1 ~]$ admintools -t restart_node -d vertica -s 10.75.7.112,10.75.7.111 -p 123456 *** Restarting nodes for database vertica *** restart host 10.75.7.111 with catalog v_vertica_node0002_catalog restart host 10.75.7.112 with catalog v_vertica_node0003_catalog 第 173 页 共 182 页 issuing multi-node restart Starting nodes: v_vertica_node0003 (10.75.7.112) v_vertica_node0002 (10.75.7.111) Starting Vertica on all nodes. Please wait, databases with large catalogs may take a while to initialize. Node Status: v_vertica_node0002: (DOWN) v_vertica_node0003: (DOWN) Node Status: v_vertica_node0002: (DOWN) v_vertica_node0003: (DOWN) Node Status: v_vertica_node0002: (DOWN) v_vertica_node0003: (DOWN) Node Status: v_vertica_node0002: (DOWN) v_vertica_node0003: (DOWN) Node Status: v_vertica_node0002: (DOWN) v_vertica_node0003: (DOWN) Node Status: v_vertica_node0002: (DOWN) v_vertica_node0003: (DOWN) Node Status: v_vertica_node0002: (DOWN) v_vertica_node0003: (DOWN) Node Status: v_vertica_node0002: (DOWN) v_vertica_node0003: (DOWN) Node Status: v_vertica_node0002: (DOWN) v_vertica_node0003: (DOWN) Node Status: v_vertica_node0002: (DOWN) v_vertica_node0003: (DOWN) Restart Nodes result: 2 [dbadmin@V1 ~]$ admintools -t restart_node -d vertica -s 10.75.7.112,10.75.7.111 -p 123456 -F *** Restarting nodes for database vertica *** restart host 10.75.7.111 with catalog v_vertica_node0002_catalog restart host 10.75.7.112 with catalog v_vertica_node0003_catalog issuing multi-node restart Starting nodes: v_vertica_node0003 (10.75.7.112) v_vertica_node0002 (10.75.7.111) Starting Vertica on all nodes. Please wait, databases with large catalogs may take a while to initialize. Node Status: v_vertica_node0002: (INITIALIZING) v_vertica_node0003: (INITIALIZING) Node Status: v_vertica_node0002: (INITIALIZING) v_vertica_node0003: (INITIALIZING) Node Status: v_vertica_node0002: (INITIALIZING) v_vertica_node0003: (INITIALIZING) Node Status: v_vertica_node0002: (DOWN) v_vertica_node0003: (DOWN) Node Status: v_vertica_node0002: (DOWN) v_vertica_node0003: (DOWN) Node Status: v_vertica_node0002: (DOWN) v_vertica_node0003: (DOWN) Node Status: v_vertica_node0002: (DOWN) v_vertica_node0003: (DOWN) Node Status: v_vertica_node0002: (DOWN) v_vertica_node0003: (DOWN) Node Status: v_vertica_node0002: (DOWN) v_vertica_node0003: (DOWN) Node Status: v_vertica_node0002: (DOWN) v_vertica_node0003: (DOWN) Restart Nodes result: 2 [dbadmin@V1 ~]$ [dbadmin@V2 ~]$ admintools -t view_cluster DB | Host | State ---------+-------------+-------------- vertica | 10.75.7.110 | INITIALIZING vertica | 10.75.7.111 | DOWN vertica | 10.75.7.112 | DOWN [dbadmin@V2 ~]$ admintools -t view_cluster DB | Host | State ---------+------+-------------- vertica | ALL | INITIALIZING [dbadmin@V2 ~]$ admintools -t view_cluster DB | Host | State 第 174 页 共 182 页 ---------+------+------- vertica | ALL | DOWN #从备份恢复 [dbadmin@V3 ~]$ vbr.py --task restore --config-file full_lizy_20140729.ini Preparing... Found Database port: 5433 Copying... [==================================================] 100% All child processes terminated successfully. restore done! [dbadmin@V2 ~]$ du -sh data 12K data [dbadmin@V2 ~]$ du -sk data 1900 data … [dbadmin@V2 ~]$ du -sk data 155840 data [dbadmin@V1 ~]$ admintools -t start_db -d vertica -p 123456 Starting nodes: v_vertica_node0003 (10.75.7.112) v_vertica_node0001 (10.75.7.110) v_vertica_node0002 (10.75.7.111) Starting Vertica on all nodes. Please wait, databases with large catalogs may take a while to initialize. Node Status: v_vertica_node0001: (INITIALIZING) v_vertica_node0002: (INITIALIZING) v_vertica_node0003: (INITIALIZING) Node Status: v_vertica_node0001: (INITIALIZING) v_vertica_node0002: (INITIALIZING) v_vertica_node0003: (INITIALIZING) Node Status: v_vertica_node0001: (INITIALIZING) v_vertica_node0002: (INITIALIZING) v_vertica_node0003: (INITIALIZING) Node Status: v_vertica_node0001: (UP) v_vertica_node0002: (UP) v_vertica_node0003: (UP) Database vertica started successfully 11.3 Catalog 文件被删除 11.3.1 删除 1 个节点 catalog 在其它实例执行以下命令重新启动失败节点,有时可能启动几次才能完成启动 #启动 vertica 失败的节点 第 175 页 共 182 页 admintools -t restart_node -s 10.75.7.112 -d vertica -p 123456 [dbadmin@V2 ~]$ admintools -t restart_node -s 10.75.7.112 -d vertica -p 123456 *** Restarting nodes for database vertica *** restart host 10.75.7.112 with catalog v_vertica_node0003_catalog issuing multi-node restart Starting nodes: v_vertica_node0003 (10.75.7.112) Starting Vertica on all nodes. Please wait, databases with large catalogs may take a while to initialize. Node Status: v_vertica_node0003: (DOWN) Node Status: v_vertica_node0003: (DOWN) Node Status: v_vertica_node0003: (DOWN) Node Status: v_vertica_node0003: (DOWN) Node Status: v_vertica_node0003: (DOWN) Node Status: v_vertica_node0003: (DOWN) Node Status: v_vertica_node0003: (DOWN) Node Status: v_vertica_node0003: (DOWN) Node Status: v_vertica_node0003: (DOWN) Node Status: v_vertica_node0003: (DOWN) Restart Nodes result: 2 [dbadmin@V2 ~]$ admintools -t restart_node -s 10.75.7.112 -d vertica -p 123456 *** Restarting nodes for database vertica *** restart host 10.75.7.112 with catalog v_vertica_node0003_catalog issuing multi-node restart Starting nodes: v_vertica_node0003 (10.75.7.112) Starting Vertica on all nodes. Please wait, databases with large catalogs may take a while to initialize. Node Status: v_vertica_node0003: (DOWN) Node Status: v_vertica_node0003: (DOWN) Node Status: v_vertica_node0003: (DOWN) Node Status: v_vertica_node0003: (UP) Restart Nodes result: 1 #启动后的 vertica 进程 [dbadmin@V3 v_vertica_node0003_catalog]$ ps -ef|grep vertica dbadmin 2347 1 0 Jul23 ? 00:00:00 /bin/bash /opt/vertica/agent/agent.sh /opt/vertica/config/users/dbadmin/agent.conf dbadmin 2359 2347 0 Jul23 ? 00:00:40 /opt/vertica/oss/python/bin/python ./simply_fast.py dbadmin 10145 1 0 15:45 ? 00:00:00 /opt/vertica/spread/sbin/spread -c /home/dbadmin/vertica/v_vertica_node0003_catalog/spread.conf dbadmin 10147 1 5 15:45 ? 00:00:01 /opt/vertica/bin/vertica -D /home/dbadmin/vertica/v_vertica_node0003_catalog -C vertica -n v_vertica_node0003 -h 10.75.7.112 -p 5433 -P 4803 dbadmin 10150 10147 0 15:45 ? 00:00:00 /opt/vertica/bin/vertica-udx-zygote 12 11 10147 debug-log-off /home/dbadmin/vertica/v_vertica_node0003_catalog/UDxLogs dbadmin 10256 9742 0 15:46 pts/2 00:00:00 grep vertica 11.3.1 删除 2 个节点 catalog 这个过程和删除 2 个节点的 data 文件类似,需要从备份恢复才能起库。 第 176 页 共 182 页 #测试过程如下 [dbadmin@V1 ~]$ admintools -t restart_node -d vertica -s 10.75.7.112,10.75.7.111 -p 123456 -F *** Restarting nodes for database vertica *** restart host 10.75.7.111 with catalog v_vertica_node0002_catalog restart host 10.75.7.112 with catalog v_vertica_node0003_catalog issuing multi-node restart Starting nodes: v_vertica_node0003 (10.75.7.112) v_vertica_node0002 (10.75.7.111) Starting Vertica on all nodes. Please wait, databases with large catalogs may take a while to initialize. Restart Nodes result: {'10.75.7.111': ['1', ["chmod: cannot access `/home/dbadmin/catalog/vertica/v_vertica_node0002_catalog': No such file or directory", 'sh: line 3: /home/dbadmin/catalog/vertica/dbLog: No such file or directory']], '10.75.7.112': ['1', ["chmod: cannot access `/home/dbadmin/catalog/vertica/v_vertica_node0003_catalog': No such file or directory", 'sh: line 3: /home/dbadmin/catalog/vertica/dbLog: No such file or directory']]} [dbadmin@V1 ~]$ [dbadmin@V1 ~]$ admintools -t view_cluster DB | Host | State ---------+-------------+-------------- vertica | 10.75.7.110 | INITIALIZING vertica | 10.75.7.111 | DOWN vertica | 10.75.7.112 | DOWN [dbadmin@V3 ~]$ vbr.py --task restore --config-file full_lizy_20140729.ini Preparing... Found Database port: 5433 Warning: Node state of v_vertica_node0001 is INITIALIZING; node must be DOWN for restore; ignoring restore on this node. Cannot safely restore to implicated subset of nodes. restore failed! [dbadmin@V1 ~]$ admintools -t stop_node -s 10.75.7.110 *** Forcing host shutdown *** Sending host shutdown command to '10.75.7.110' [dbadmin@V1 ~]$ admintools -t view_cluster DB | Host | State ---------+------+------- vertica | ALL | DOWN [dbadmin@V3 ~]$ vbr.py --task restore --config-file full_lizy_20140729.ini Preparing... Found Database port: 5433 Copying... [==================================================] 100% All child processes terminated successfully. restore done! 11.4 私有网络 down 集群 crash 当按照 vertica 集群的私有网络异常 down 时,集群的节点无法正常运行,以下是私有网络异常时集群 第 177 页 共 182 页 crash 的案例。 #DWS 测试环境,主机重启私有网络启动异常,集群 crash 案例 2014-09-27 10:35:48.006 LowDiskSpaceCheck:0x7f8274019c10-d0000000023f48 [Txn] Rollback Txn: d0000000023f48 'LowDiskSpaceCheck' 2014-09-27 10:35:48.007 LowDiskSpaceCheck:0x7f8274019c10 [Util] Task 'LowDiskSpaceCheck' enabled 2014-09-27 10:35:48.906 Init Session:0x7f8264010540 @v_dws_node0004: 00000/2705: Connection received: host=192.168.88.4 port=38766 (connCnt 1) 2014-09-27 10:35:48.906 Init Session:0x7f8264010540 @v_dws_node0004: 00000/4540: Received SSL negotiation startup packet 2014-09-27 10:35:48.906 Init Session: [dbadmin@dws4 v_dws_node0004_catalog]$ ifconfig eth0 Link encap:Ethernet HWaddr 00:0C:29:75:7B:91 inet addr:10.75.10.44 Bcast:10.75.10.255 Mask:255.255.255.0 inet6 addr: fe80::20c:29ff:fe75:7b91/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:99090 errors:0 dropped:0 overruns:0 frame:0 TX packets:12801 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:11317863 (10.7 MiB) TX bytes:2297527 (2.1 MiB) eth1 Link encap:Ethernet HWaddr 00:0C:29:75:7B:9B inet6 addr: fe80::20c:29ff:fe75:7b9b/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:83602 errors:0 dropped:0 overruns:0 frame:0 TX packets:2864 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:8739271 (8.3 MiB) TX bytes:976472 (953.5 KiB) lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 inet6 addr: ::1/128 Scope:Host UP LOOPBACK RUNNING MTU:16436 Metric:1 RX packets:6 errors:0 dropped:0 overruns:0 frame:0 TX packets:6 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:346 (346.0 b) TX bytes:346 (346.0 b) 12. 管理控制台(MC) 12.1 管理控制台架构 管理控制台(Management Console)的架构如下图所示: 第 178 页 共 182 页 MC 的 web 应用使用使用 5450 端口进行 node-to-MC 的通信,主要完成以下任务:  管理一个或者多个 vertica 数据库集群  发生快速更新从 MC 到 web 浏览器  存储和报告 MC metadata 如,alert、event、节点状态、MC 用户等信息在轻量级数据库 Derby  获取负载历史信息 MC agent 是指运行在每个节点的底层进程,默认使用端口 5444 进行 MC-to-node 和 node-to-node 通信, agent 监控由 MC 管理的 vertica 数据库并对 MC 进行报告,主要包括  提供本地访问,通过某一数据库实例进行控制和管理;  报告 admintools 和 vertica 日志文件的 log-level 数据;  缓存详细长任务的信息,类似 create/start/stop 数据库的操作,可以通过浏览器观察;  跟踪数据收集的变化、监控工具以及跟 MC 的通信更新等;  MC 和集群所有节点间通信通过 webhook 自动共享信息和报告集群的问题; 12.2 管理控制台的安装和配置 管理控制台的安装步骤: 1、下载 MC 的 package((vertica-console-.)) 2、逐个节点安装 Management Console rpm 包 第 179 页 共 182 页 3、选择其中一个节点登录到 https://hostname:5450/webui,配置操作系统 dbadmin 用户的 gid、密码、 home 目录等,以及数据库 dbadmin 用户的密码,数据库的 data、catalog 路径。 4、以上配置完成之后节点的 webui agent 自动重启,重启完成之后即可登录。 MC 数据库导入: 1、选择主页上的 Databases and Clusters 按钮,点击左侧+号上的 Import 按钮。 2、输入数据库的 IP 地址,如:192.168.31.30。 3、输入 apikey,apikey 的信息,该信息可以在/opt/vertica/config/apikeys.dat 中找到。 4、完成以上操作即可导入相关的数据库的数据。 12.3 管理控制台的维护 12.3.1 管理控制台重启 通过管理控制台的 webui 或者 command 都可以进行管理控制台的相关维护工作。通过浏览器的 MC Interface 进行重启的步骤如下: 1、 使用 adminstrator 登录到 MC 2、 在 MC 的主页面 点击 Diagnostics 3、 点击 Restart Console,然后点击 ok 继续或者点击 cancel 退出 也可以使用命令行进行类似的管理操作: 1、 使用 root 登录到安装 MC Console 的节点 2、 运行 vertica-consoled 脚本进行重启 # /etc/init.d/vertica-consoled { stop | start | restart } 12.3.2 重设 MC 到初始状态 个别时候可能需要把 MC 中已经配置的信息和收集到的数据全部清除,可以使用这里描述的方法。如果需要 把 MC 重设到初始状态,则参考如下步骤: 1、 使用 adminstrator 登录到 MC 2、 在 MC 的主页面 点击 Diagnostics 3、 点击 Factory Reset,然后点击 ok 继续或者点击 cancel 退出 该操作之后 MC 将类似一个全新安装的 MC,需要重新配置相关信息。 第 180 页 共 182 页 12.4 修改 MC agent 端口 修改 MC 的端口需要两个步骤:命令行修改 config.py 文件和浏览器修改 MC 设置。 12.4.1 修改 config.py 中的 Agent Port 1、 root 用户登录到集群的任何一个节点的目录:/opt/vertica/agent 2、 编辑文件 config.py 修改端口 agent_port = 5444 到新的指定端口 3、 复制该文件到集群其它节点的目录:/opt/vertica/agent 4、 逐个节点进行 agent 的重启,命令如下 # /etc/init.d/vertica_agent restart 12.5 MC 的用户管理 MC 有一套单独的用户,你可以参考以下步骤创建 MC 的用户: 1、以管理员身份登录到 MC 的主页面,点击 MC Settings > User management 2、点击 Add 按钮 3、输入 MC 用户名,MC 用户会关联一个 db 的用户,但是他们的用户名不一定相同 4、生成一个随机密码或者自定义一个密码 5、选择可选的用户邮箱 6、选择 MC configuration permissions 的级别,如 IT 7、选择 DB access levels section,点击右侧添加按钮,添加关联的数据库用户,中间需要选择数据库、输 入用户名、密码和访问级别 ADMIN、IT、USER,如 IT 8、选择 Status 为 Enabled 9、点击右下角的 ADD user 按钮 第 181 页 共 182 页 13. 名词解释 13.1 Pro-join Projection Pre-join projections 解释:查询指定的 Projection 的一个子集,该 Projection 存储了一个大表和一个或多 个维度表的关联的结果。跟其它查询指定的 Projection 一样,每当发生插入或加载操作时 vertica 计算并存储最 新的结果到这些表中。当运行表关联查询的时候这提供了显著的性能提升。 Pre-join projections 存放的数据是根据查询或者类似的一组查询谓词排序的,这同样能够提升查询的性能。 Pre-join projections 只能在表的主键和外键上使用内连接,不运行使用外连接。 A subset of query specific projections that are used to store the results of a join between a single large (fact/anchor) table in the logical schema with one or more dimension tables. As with other query-specific projections, HP Vertica calculates and stores a new result set each time data is inserted or loaded into these tables. This provides a significant performance advantage over joining tables when queries are run. The result set of a pre-join projection is typically sorted for a specific query or commonalities in a class of queries based on the query predicate. This provides optimal query performance. Pre-join projections can have only inner joins between tables on their primary and foreign key columns. Outer joins are not allowed in pre-join projections. Vertica 在查询表之间基于主外键等值连接时可以使用 Pre-join projections。当使用 Pre-join projections 查询时, 第 182 页 共 182 页
还剩181页未读

继续阅读

下载pdf到电脑,查找使用更方便

pdf的实际排版效果,会与网站的显示效果略有不同!!

需要 10 金币 [ 分享pdf获得金币 ] 13 人已下载

下载pdf

pdf贡献者

liyao

贡献于2017-01-17

下载需要 10 金币 [金币充值 ]
亲,您也可以通过 分享原创pdf 来获得金币奖励!
下载pdf