Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >使用Vite重构Vue3项目

使用Vite重构Vue3项目

作者头像
神奇的程序员
发布于 2022-10-30 06:16:28
发布于 2022-10-30 06:16:28
2K00
代码可运行
举报
运行总次数:0
代码可运行

前言

截止发文时间,vite正式版已经发布快2年时间了,vue3也发布到3.2版本了,它的周边设施基本上已经齐活了。也是时候再次重构下我那个vue3.0的开源项目了。

本篇文章就记录下我的重构过程,欢迎各位感兴趣的开发者阅读本文。

环境搭建

1年多前,我用Vue Cli 4.5构建的此项目,有关此项目的更多细节请移步我的另一篇文章使用Vue3重构Vue2项目。同样的,从CLI迁移到Vite仍然是在package.json中添加vite的依赖项,在项目中添加它的配置文件。

此次项目构建还加入了volta的相关配置,对此感兴趣的开发者请移步:强大的JavaScript工具管理器Volta

新增vite相关依赖项

我们打开package.json,找到devDependencies字段,移除CLI相关的依赖,添加vite相关的依赖,如下所示:

  • +绿色标识代表新增
  • -红色标识代表移除
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{
 "dependencies": {
-   "compression-webpack-plugin": "^5.0.1",
 },
 "devDependencies": {
+   "@vitejs/plugin-vue": "^3.0.0",
+   "vite": "^3.0.0",
+    "vue-tsc": "^0.38.4",
+    "@types/node": "^18.6.3",
-    "sass-loader": "^8.0.2",
-    "@vue/cli-plugin-babel": "~4.5.0",
-    "@vue/cli-plugin-eslint": "~4.5.0",
-    "@vue/cli-plugin-router": "~4.5.0",
-    "@vue/cli-plugin-typescript": "~4.5.0",
-    "@vue/cli-plugin-vuex": "~4.5.0",
-    "@vue/cli-service": "~4.5.0",
-   "@vue/compiler-sfc": "^3.0.0-0"
- 
 }
}

随后,我们找到scripts字段,修改项目的运行与构建命令。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{
  "scripts": {
    "serve": "vite --open",
    "build": "vue-tsc --noEmit && vite build",
    "preview": "vite preview"
  }
}

vite3.x版本要求node版本必须大于14.18.0,因此我们需要在engines字段中做一下提示,如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{
  "engines": {
    "npm": "please-use-yarn",
    "yarn": ">= 1.0.0",
    "node": ">= 14.18.0"
  }
}

除了上述配置外,我们还需要在项目的根目录创建.npmrc文件,写入下述内容:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
engine-strict = true

配置完成后,我们执行在终端执行yarn install安装依赖即可。

在上述配置中,我们还强制设置了yarn作为项目的包管理工具,如果项目开发成员使用了npm install则不会开始安装依赖并提示其使用yarn来安装依赖。

添加vite配置文件

在vite中,index.html已经从public文件夹迁移到项目的根目录下了,官方文档对此的解释为:在开发期间 Vite 是一个服务器,而 index.html 是该 Vite 项目的入口文件。

有关此变更的详细解释请移步:index.html 与项目根目录

接下来,我们在项目的根目录创建index.html文件(将public目录下的文件删除)

  • 引入静态文件时不需要使用%PUBLIC_URL%作为占位符,可以直接写/来访问,vite会将其解析到public根目录下
  • 通过<script type="module" src="...">标签直接指向Vue的入口文件(文件后缀可以为js或者ts)
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" type="image/svg+xml" href="/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>chat-system</title>
  </head>
  <body>
    <div id="app"></div>
    <script type="module" src="/src/main.ts"></script>
  </body>
</html>

注意:如果你的项目比较复杂,有多个入口,那么就将index.html文件放到对应入口的根目录下。

最后,我们创建vite.config.ts文件,配置代码如下所示:

  • 设置开发环境的端口号
  • 设置路径别名
  • 设置打包后base地址以及打包输出目录
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import { defineConfig } from "vite";
import { resolve } from "path";
import vue from "@vitejs/plugin-vue";
const IS_PRODUCTION = process.env.NODE_ENV === "production";

export default defineConfig({
  plugins: [vue()],
  server: {
    host: true,
    port: 8020,
    proxy: {}
  },
  resolve: {
    // 设置路径别名
    alias: {
      "@": resolve(__dirname, "./src"),
      "*": resolve("")
    }
  },
  base: IS_PRODUCTION ? "/chat-system" : "./",
  define: {
    "process.env": {}
  },
  build: {
    outDir: resolve(__dirname, "dist")
  }
});

注意:我的项目配置比较简单,它只有一个入口,打包后只会部署到生产环境。如果你的项目较为复杂,也不必太过担心,你的应用场景vite也是支持的,按照文档进行相关的配置就好,如下所示:

  • 自定义构建
  • 多页面应用模式
  • 环境变量和模式

当你的项目有多个入口时,期望通过不同命令来启动不同项目时,你可以使用yarn的--cwd指令来指定其运行时的工作目录。

例如:你有两个入口,那么就在src目录下创建两个文件夹:**A、B **。A和B中分别有自己的index.html、main.ts以及package.json文件(配置start、build命令,传入不同的参数来启动/构建不同入口的项目)

根目录的package.json中你就可以配置启动/构建命令为:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{
  "scripts": {
    "dev:A": "yarn --cwd ./src/A run start",
    "dev:B": "yarn --cwd ./src/B run start",
    "build:A": "yarn --cwd ./src/A run build",
    "build:B": "yarn --cwd ./src/B run build",
    "build": "vue-tsc --noEmit && vite build",
    "preview": "vite preview"
  },
}

最后,我们以A入口为例,列举下package.json文件中的配置:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{
  "name": "A",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "scripts": {
    "start": "vite serve --config ../../vite.config-A.ts --mode development",
    "build": "vue-tsc --noEmit && vite build --config ../../vite.config-A.ts --mode production"
  }
}

升级Vue周边依赖项

vue3.2的单文件组件引入了setup规范,它可以让代码变得更简洁,可以使用纯 TypeScript 声明 props 和抛出事件,有着更好的运行时性能。这些优点让我有了升级vue版本的动力,之前的3.0版本写起来很臃肿,需要return一大堆东西,甚是麻烦。

打开package.json文件作出下述变动:

  • 更新了vue、router、vuex的版本号
  • 新增了vueuse包,这是一个基于 Composition API 的实用函数集合,封装了一些常用的功能(实时获取鼠标位置、防抖、节流、获取客户端系统主题等),可以避免一些重复性的工作内容,大大提升开发效率。
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{
 "dependencies": { 
-  "vue": "^3.0.0-0",
-   "vue-class-component": "^8.0.0-0"
-  "vue-router": "^4.0.0-0",
-  "vuex": "^4.0.0-0",
+   "vue": "^3.2.37",
+   "vue-router": "^4.1.3",
+   "vuex": "^4.0.2",
+   "@vueuse/components": "^8.9.2",
+   "@vueuse/core": "^8.9.2"
 }
}

最后执行yarn install即可完成整个环境的搭建,本章节重构完成后的完整文件请移步:

  • .npmrc
  • index.html
  • package.json
  • vite.config.ts

经验分享

本章节就跟大家分享下,我切到新环境后做的一些优化点以及遇到的问题和解决方案。

本章节修改到的文件,完整文件代码如下:

  • package.json
  • tsconfig.json

require不存在

一切准备就绪后,按下了项目启动按钮,很快啊,651ms项目就启动了,不愧是vite速度就是快,嘴角疯狂上扬。

image-20220804230003937

浏览器加载完项目后,我傻眼了,我的登陆界面呢🌚?顺势打开控制台,发现报错require is not defined

image-20220804230914786

解决方案

打开Login.vue文件后,发现我用require导入了一些图片文件,在VueCLI环境下的require会交给webpack处理。在vite中是不存在的,那么我们就需要查看vite是怎么处理静态文件了。

翻了下文档后,在静态资源处理章节发现他有两种处理方法:

  • 通过import语句直接导入图片
  • 通过new URL来导入图片

我打算将所有组件都重构为setup形式,因此直接使用import方式来导入图片可以保持组件的一致性,可以大大提升可读性。

我们写个简单的demo来尝试下,如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<template>
  <img :src="loginUndo" alt="" />
</template>

<script lang="ts" setup>
import loginUndo from "@/assets/img/login/LoginWindow_BigDefaultHeadImage@2x.png";
</script>

<style scoped></style>

已经可以正确解析出图片的路径了。

image-20220804234223781

注意:本文不会过多讲解setup的语法,对此不了解的开发者请移步:单文件组件 - script setup new URL方式可以用来引入一个动态资源,例如:你有一份json配置文件,里面描述了图片的文件名,这些图片是放在项目中的,他们的访问前缀都一样,此时你就可以通过遍历json文件通过此方式来引入这些图片。

vue相关模块不存在

我试图从vue的包中导入shallowRef时,编辑器报错: TS2305: Module 'xxx' has no exported member 'shallowRef'.

image-20220806102302026

解决方案

经过一番排查后,是因为项目typescript版本是3.x,跟3.2版本的vue不兼容,需要将其升级至4.x版本。

打开package.json文件,作出如下所示的修改,重新执行yarn install命令即可。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{
  "devDependencies": {
-    "typescript": "~3.9.3",
+    "typescript": "~4.7.4",
  }
}

setup中的变量警告未被使用

当我在setup中声明了一个函数或者导入了一个文件,在template中已经使用了,但是他却报错ESLint: 'xx' is assigned a value but never used.(@typescript-eslint/no-unused-vars)

image-20220806231446097

解决方案

eslint-plugin-vue 插件的Issues中看到有人遇到了跟我同样的问题,在v9.0.0: regression in unused variables in script setup中我找到了解决方案。

我们需要升级下@vue/eslint-config-typescripteslint-plugin-vue的版本号,如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{
  "devDependencies": {
    "@vue/eslint-config-typescript": "^11.0.0",
    "eslint-plugin-vue": "^9.0.0"
  }
}

随后在eslint的配置文件中,添加parser属性,重新执行yarn install命令即可。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
module.exports = {
+  parser: 'vue-eslint-parser'
}

模块隔离

Vite 使用 esbuild 来转译 TypeScript,并受限于单文件转译的限制,因此需要在ts的配置文件中将isolatedModules属性设置为true。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{
    "compilerOptions": {
       "isolatedModules": true
    }
}

process不存在

路由配置文件中,我们需要从process中获取BASE_URL,此时编辑器报错: TS2591: Cannot find name 'process'. Do you need to install type definitions for node? Try npm i --save-dev @types/node and then add 'node' to the types field in your tsconfig.

image-20220806105226383

解决方案

由于vite中已经没有process了,需要用import.meta来代替,那么上述的路由配置文件就应该改为:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL), // 地址栏不带#
  routes
});

无法导入json文件

在表情面板模块,我将每个表情都放入了json文件中。在vite中引入文件需要使用import,改了写法后,发现它报错:Cannot find module 'xx.json'. Consider using '--resolveJsonModule' to import module with '.json' extension.

image-20220806111708308

解决方案

我们需要在ts的配置文件中添加resolveJsonModule属性,如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{
  "compilerOptions": {
+   "resolveJsonModule": true
  }
}

使用vite提供的对象

当我想使用vite所提供的glob属性时,发现编辑器报错: TS2339: Property 'glob' does not exist on type 'ImportMeta'.

解决方案也很简单,我们只需要在ts的配置文件中添加vite/client即可,如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{
 "compilerOptions": {
   "types": [
+     "vite/client"
    ]
 }
}

获取全局属性

当我们使用一些第三方库的时候它会在globalProperties挂载一些方法,当在ts+setup环境下使用时,会出现类型无法推导问题,如下所示:

  • 第三方库提供了一个$connect方法
  • 我们通过proxy来访问
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<script lang="ts" setup>
  import {
    getCurrentInstance,
    onMounted,
    ComponentInternalInstance
  } from "vue";

  onMounted(() => {
    const { proxy } = getCurrentInstance() as ComponentInternalInstance;
    proxy.$connect();
  })
</script>

他会出现报错: TS2339: Property 'xx' does not exist on type 'ComponentPublicInstance{}, {}, {}, {}, {}, {}, {}, {}, false, ComponentOptionsBase >'.

image-20220809103616969

解决方案

我们可以在type目录下新建一个global文件夹,在这里存放一些我们扩展出来的全局方法。

如下所示,我们:

  • 创建了一个useCurrentInstance方法
  • globalProperties属性暴露出去
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import { ComponentInternalInstance, getCurrentInstance } from "vue";
export default function useCurrentInstance() {
  const { appContext } = getCurrentInstance() as ComponentInternalInstance;
  const proxy = appContext.config.globalProperties;
  return {
    proxy
  };
}

我们在组件中使用暴露出来的proxy即可,如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<script lang="ts" setup>
 import useCurrentInstance from "@/type/global/UseCurrentInstance";

  onMounted(() => {
    const { proxy } = useCurrentInstance();
    proxy.$connect();
  })
</script>

无法识别NodeJS类型

我们在给setintervalsetTimeout指定类型时,会用到NodeJS模块,会出现报错:ESLint: 'NodeJS' is not defined.(no-undef)

这个问题的解决方案是:打开eslint的配置文件在globals对象中添加NodeJS选项,如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{
  globals: {
    NodeJS: true
  }
}

除了将类型声明为NodeJS.Timeout外,我们还可以将其声明为number类型,但是需要携带window前缀(window.setinterval/window.setTimeout)

管理静态资源

当我们在组件中使用import导入很多静态资源时,组件看起来会很杂乱。此时我们可以将其按照功能类型进行拆分。我的做法如下:

  • 在src下创建resource文件夹
  • 根据功能类型创建ts文件,将其导出
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import defaultAvatar from "@/assets/img/login/LoginWindow_BigDefaultHeadImage@2x.png";
import defaultLoginBtnIcon from "@/assets/img/login/icon-enter-undo@2x.png";
import loginUndo from "@/assets/img/login/icon-enter-undo@2x.png";
import loginBtnHover from "@/assets/img/login/icon-enter-hover@2x.png";
import loginBtnDown from "@/assets/img/login/icon-enter-down@2x.png";

export {
  defaultAvatar,
  defaultLoginBtnIcon,
  loginUndo,
  loginBtnHover,
  loginBtnDown
};

image-20220808212416992

分离模版与逻辑代码

我的项目中有一个很复杂的组件,有上千行代码,去年我用CompositionAPI优化了一版,将组件中所有的方法都拆分成了一个个独立的ts文件,做到了逻辑代码与模版代码分离,模版需要什么方法我就通过import导入进来,最后return给模版。

在拆分出来的文件中,是没有办法访问vue提供的一些内置属性的,比如:defineProps、defineEmits、getCurrentInstance。因此我想了一个奇妙的方法:将这些无法访问的属性都存起来。具体的做法请移步我另一篇文章:使用Vue3的CompositionAPI来优化代码量-创建InitData.ts文件

适配方案

vue3.2的setup语法糖支持import进来的方法都能在模版中直接使用,那我们的组件又可以精简下了,我花了亿点点时间对其进行了适配🤒

之前我们想获取组件的emit需要从context中拿,props声明并从setup函数的参数中获取,如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<script>
export default defineComponent({
  name: "message-display",
  props: {
    listId: String, // 消息id
    messageStatus: Number, // 消息类型
    buddyId: String, // 好友id
    buddyName: String, // 好友昵称
    serverTime: String // 服务器时间
  },
  setup(props, context) {
  // 访问emit
  context.emit
 }
})
</script>

现在我们就不用这么麻烦了,直接通过defineProps、defineEmits获取即可,如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<script lang="ts" setup>
// 获取父组件传递值
const props = defineProps<{
  listId: string; // 消息id
  messageStatus: number; // 消息类型
  buddyId: string; // 好友id
  buddyName: string; // 好友昵称
  serverTime: string; // 服务器时间
}>();
const emit = defineEmits<{
  (
    e: "update-last-message",
    msgObj: {
      text: string;
      id: string;
      time: string;
    }
  ): void;
}>();

// 事件监听函数,传入props和emit将其存储到initData中
const { userID, onlineUsers } = eventMonitoring(props, emit) as {
  userID: ComputedRef<string>;
  onlineUsers: ComputedRef<number>;
};
</script>

此组件重构后的完整代码请移步:

  • message-display.vue
  • EventMonitoring.ts

项目地址

至此,项目的重构工作就结束了。本文重构好的项目代码地址:

  • chat-system

写在最后

至此,文章就分享完毕了。

我是神奇的程序员,一位前端开发工程师。

如果你对我感兴趣,请移步我的个人网站,进一步了解。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-08-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 神奇的程序员 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
⏱⏱动态SQL略知一二??
在使用 EF或者写 SQL语句时,查询条件往往是这样一种非常常见的逻辑:如果客户填了查询信息,则查询该条件;如果客户没填,则返回所有数据。
架构师修行之路
2020/02/11
6610
包含列的索引:SQL Server索引进阶 Level 5
作者David Durant,2011/07/13 关于系列 本文属于Stairway系列:Stairway to SQL Server Indexes 索引是数据库设计的基础,并告诉开发人员使用数据库关于设计者的意图。 不幸的是,当性能问题出现时,索引往往被添加为事后考虑。 这里最后是一个简单的系列文章,应该使他们快速地使任何数据库专业人员“快速”。 ---- 前面的级别引入了聚簇和非聚簇索引,突出了以下各个方面: 表中每一行的索引总是有一个条目(我们注意到这个规则的一个例外将在后面的级别中进行讨论)。
Woodson
2018/07/19
2.6K0
SQL Server索引简介:SQL Server索引进阶 Level 1
作者:David Durant,2014/11/05(首次发布:2011/02/17) 关于系列 本文属于进阶系列的:Stairway to SQL Server Indexes 索引是数据库设计的基础,并告诉开发人员使用数据库大量关于设计人员的意图。不幸的是,当性能问题出现时,索引通常被添加为事后的想法。最后这一系列简单的文章,应该能使任何数据库专业人员快速的“加快速度”。 ---- 此第一级引入SQL Server索引:数据库对象,使SQL Server能够在最短时间内查找和/或修改所请求的数据,使用最
Woodson
2018/07/18
1.6K0
sql sever 索引
微软的SQL SERVER提供了两种索引:聚集索引(clustered index,也称聚类索引、簇集索引)和非聚集索引(nonclustered index,也称非聚类索引、非簇集索引)
week
2018/08/27
4880
列存储索引1:初识列存储索引
     2012以后提供了一种不同于传统B树结构的索引类型,就是内存列存储索引。这种索引应用了一种基于列的存储模式,也是一种新的查询执行的批处理模式,并且为特定的负载提供了巨大的性能提升。它是如何构建?如何工作?又是为什么能对性能有如此大的提升,接下来我们用简明的描述和详尽的示例来解释说明。      那么列存储索引究竟是什么?大多数时候,列存储索引被描述作为一种数据仓库和数据报表的功能。事实上,你最有可能就是在这种情况下利用这种索引。然而,即使在OLTP数据库中,你也会遇到一些要从大量数据表中获取数据的
用户1217611
2018/01/30
1.6K0
列存储索引1:初识列存储索引
深入非聚集索引:SQL Server索引进阶 Level 2
作者David Durant,2017/10/18(首次发布于:2014/11/26) 关于系列 本文属于进阶系列:Stairway to SQL Server Indexes 索引是数据库设计的基础,并告诉开发人员使用数据库关于设计者的意图。 不幸的是,当性能问题出现时,索引往往被添加为事后考虑。 这里最后是一个简单的系列文章,应该使他们快速地使任何数据库专业人员“快速” SQL Server索引阶段1中的级别1通常引入了SQL Server索引,特别引入了非聚簇索引。作为我们的第一个案例研究,我们演示了
Woodson
2018/07/19
1.6K0
SQL索引一步到位
SQL索引在数据库优化中占有一个非常大的比例, 一个好的索引的设计,可以让你的效率提高几十甚至几百倍,在这里将带你一步步揭开他的神秘面纱。   1.1 什么是索引?   SQL索引有两种,聚集索引和非聚集索引,索引主要目的是提高了SQL Server系统的性能,加快数据的查询速度与减少系统的响应时间 下面举两个简单的例子: 图书馆的例子:一个图书馆那么多书,怎么管理呢?建立一个字母开头的目录,例如:a开头的书,在第一排,b开头的在第二排,这样在找什么书就好说了,这个就是一个聚集索引,可是很多人借书找某某作
Java高级架构
2018/07/20
1.6K0
v$sysstat表解释
按照OracleDocument中的描述,v$sysstat存储自数据库实例运行那刻起就开始累计全实例(instance-wide)的资源使用情况。
jack.yang
2025/04/05
730
聚集索引:SQL Server 进阶 Level 3
作者:David Durant,2013/01/25(首次发布于:2011/06/22) 关于系列 本文是属于Stairway系列:Stairway to SQL Server Indexes 索引是数据库设计的基础,并告诉开发人员使用数据库关于设计者的意图。不幸的是,当性能问题出现时,索引往往被添加为事后考虑。这里最后是一个简单的系列文章,应该使他们快速地使任何数据库专业人员“快速” 这个阶段的前面的层次提供了一般索引和非聚集索引的概述。它以下面关于SQL Server索引的关键概念结束。当请求到达您的数
Woodson
2018/07/19
1.2K0
[Oracle]-[SORT AGGREGATE]-count与索引
Oracle10g: create table t_count as select * from dba_objects; create index t_count_i on t_count(object_id): 分别用: select count(*) from t_count; select count(object_id) from t_count; select count(object_name) from t_count; 查看是否使用索引对count查询性能起到作用。 它们的执行计划: SQL> select count(*) from t_count; Execution Plan ---------------------------------------------------------- Plan hash value: 2197880521 ---------------------------------------------------------------------- | Id  | Operation           | Name    | Rows  | Cost (%CPU)| Time     | ---------------------------------------------------------------------- |   0 | SELECT STATEMENT   |             |           1 |          39   (0)| 00:00:01 | |   1 |  SORT AGGREGATE    |             |           1 |                  |             | |   2 |   TABLE ACCESS FULL| T_COUNT | 12028 |          39   (0)| 00:00:01 | ---------------------------------------------------------------------- Note -----    - dynamic sampling used for this statement SQL> select count(object_name) from t_count;
bisal
2019/01/29
8950
SQL Server 深入解析索引存储(下)
概述 非聚集索引与聚集索引具有相同的 B 树结构,它们之间的显著差别在于以下两点: 基础表的数据行不按非聚集键的顺序排序和存储。 非聚集索引的叶层是由索引页而不是由数据页组成。 既可以使用聚集索引来为表或视图定义非聚集索引,也可以根据堆来定义非聚集索引。非聚集索引中的每个索引行都包含非聚集键值和行定位符。此定位符指向聚集索引或堆中包含该键值的数据行。 非聚集索引行中的行定位器或是指向行的指针,或是行的聚集索引键,如下所述: 如果表是堆(意味着该表没有聚集索引),则行定位器是指向行的指针。该指针由文件标
逸鹏
2018/04/11
9370
SQL Server 深入解析索引存储(下)
SQL Server 2014聚集列存储索引
 转发请注明引用和原文博客(https://cloud.tencent.com/developer/user/1217611/activities) 简介   之前已经写过两篇介绍列存储索引的文章,但是只有非聚集列存储索引,今天再来简单介绍一下聚集的列存储索引,也就是可更新列存储索引。在SQL Server 2012中首次引入了基于列存储数据格式的存储方式。叫做“列存储索引”。前一篇我已经比较了行存储索引与非聚集的列存储索引(https://cloud.tencent.com/developer/artic
用户1217611
2018/01/30
1.1K0
SQL Server 2014聚集列存储索引
SQL Server 2014聚集列存储索引
  之前已经写过两篇介绍列存储索引的文章,但是只有非聚集列存储索引,今天再来简单介绍一下聚集的列存储索引,也就是可更新列存储索引。在SQL Server 2012中首次引入了基于列存储数据格式的存储方式。叫做“列存储索引”。前一篇我已经比较了行存储索引与非聚集的列存储索引(http://www.cnblogs.com/wenBlog/p/5682024.html)。其中对于在小表的指定值或者小范围的查询来讲,尤其针对事务性的负载行存储是很合适的。但是对于分析性负载像数据仓库和BI,在查询中将会对大量数据进行全扫描,例如事实表,这时候列存储索引就是更好地选择。
用户1217611
2018/09/28
1.1K0
SQL Server 2014聚集列存储索引
SqlServer 资源消耗查询
SqlServer 的“读写查”占了整个程序的60%,特别是效能这块,在小数据还好,如果去到大数据那就麻烦了,以前做过一个测试就是批量复制和单条复制的效率问题,感兴趣的同学可以查查我以前写的文档,今天就说说如何查询SqlServer的资源消耗情况,这样就能对应问题的根本。。。
谭广健
2020/08/11
2.1K0
《T-SQL查询》读书笔记Part 3.索引的基本知识
索引优化是查询优化中最重要的一部分,索引是一种用于排序和搜索的结构,在查找数据时索引可以减少对I/O的需要;当计划中的某些元素需要或是可以利用经过排序的数据时,也会减少对排序的需要。某些方面的优化可以适度提高性能,而索引优化经常可以大幅度地提高查询性能。
Edison Zhou
2018/08/21
7530
《T-SQL查询》读书笔记Part 3.索引的基本知识
一个用 Oracle 函数索引进行优化的例子
该文介绍了如何使用Oracle函数索引优化查询性能。通过一个例子,展示了在查询中添加函数索引后,查询速度大大提高。同时还介绍了如何使用索引进行排序,以及如何使用analyze命令来查看统计信息。
用户1148526
2018/01/03
1.8K0
SQLSERVER数据库死锁与优化杂谈
当数据库死锁时,SqlServer会释放一个优先级较低的锁,让另一个事务运行;所以,即时去捕捉数据库死锁,是挺不容易的。
Kiba518
2019/03/05
2.2K0
程序猿是如何解决SQLServer占CPU100%的
文章目录 遇到的问题 使用SQLServer Profiler监控数据库 SQL1:查找最新的30条告警事件 SQL2:获取当前的总报警记录数 有哪些SQL语句会导致CPU过高? 查看SQL的查询计划
逸鹏
2018/04/11
1.6K0
程序猿是如何解决SQLServer占CPU100%的
【DB笔试面试622】在Oracle中,说说COUNT(*)计算行数有哪些优化手段?
位图索引可以按很高密度存储数据,因此往往比B树索引小很多,前提是在基数比较小(列重复度比较高)的情况下。位图索引是保存空值的,因此可以在COUNT中利用。位图索引不太适合OLTP类型数据库。物化视图是应用在数据要求不怎么及时的场景下。若表频繁更新,则不适合缓存结果集。
AiDBA宝典
2019/09/29
9810
INDEX FULL SCAN vs INDEX FAST FULL SCAN
     INDEX FULL SCAN 与 INDEX FAST FULL SCAN两个长相差不多,乃是一母同胞,因此既有其共性,也有其个性。两者来说其共性是不用扫描表而是通过索引就可以直接返回所需要的所有数据。这对提高查询性能而言,无疑是一个难得的数据访问方式之一,因为索引中存储的数据通常是远小于原始表的数据。下面具体来看看两者之间的异同。
Leshami
2018/08/14
2.5K0
推荐阅读
相关推荐
⏱⏱动态SQL略知一二??
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验