首页
留言
友情链接
标签页
Search
1
如何使用JavaScript获取和设置CSS root变量值
1,073 阅读
2
中国历史朝代顺序图
677 阅读
3
那些顶级不落俗套的“美好祝福”
564 阅读
4
春和 《江海共余生》
534 阅读
5
hyperf常用命令
411 阅读
分享
Web前端
html&css
javascript
Vue
shopify
shoplazza
后端
ThinkPHP
YII2
服务器端
软件安装
问题合集
故事
诗词
生活
学习
学科
语文
数学
英语
物理
化学
生物
政治
历史
地理
自然
其他
抖音
快手
小视频
随笔
易经
书摘
登录
/
注册
Search
标签搜索
一年级语文
sunshine
累计撰写
162
篇文章
累计收到
15
条评论
首页
栏目
分享
Web前端
html&css
javascript
Vue
shopify
shoplazza
后端
ThinkPHP
YII2
服务器端
软件安装
问题合集
故事
诗词
生活
学习
学科
语文
数学
英语
物理
化学
生物
政治
历史
地理
自然
其他
抖音
快手
小视频
随笔
易经
书摘
页面
留言
友情链接
标签页
搜索到
161
篇与
的结果
2023-03-18
Centos7 编译安装MySQL5.7
下载mysql文件包wget https://downloads.mysql.com/archives/get/p/23/file/mysql-5.7.38-linux-glibc2.12-x86_64.tar.gz下载完成后解压 将mysql-5.7.38-linux-glibc2.12-x86_64重命名为mysqltar -zxvf mysql-5.7.38-linux-glibc2.12-x86_64.tar.gz mv mysql-5.7.38-linux-glibc2.12-x86_64 mysq创建用户组和用户并修改权限groupadd mysql useradd -r -g mysql mysql创建数据目录并赋予权限mkdir -p /data/mysql chown mysql:mysql -R /data/mysql创建mysql 用户组和用户groupadd mysql useradd -r -g mysql mysql卸载CentOS7系统自带的数据库查看系统自带的Mariadbrpm -qa|grep mariadb卸载系统自带的Mariadbrpm -e --nodeps mariadb-libs-5.5.68-1.el7.x86_64删除etc目录下的my.cnf ,后面再重新建。这里的etc目录在根目录下面。rm /etc/my.cnf安装mysql5.7 解压安装mysql安装包到目录下tar -zxvf mysql-5.7.36-linux-glibc2.12-x86_64.tar.gz修改mysql-5.7.36-linux-glibc2.12-x86_64名称为mysql5.7mv mysql-5.7.36-linux-glibc2.12-x86_64 mysql5.7更改mysql5.7 目录下所有文件夹所属的用户组、用户以及权限chown -R mysql:mysql /usr/software/mysql5.7 chmod -R 755 /usr/software/mysql5.7进入/usr/software/mysql5.7/bin/目录,编译安装并初始化mysql,务必记住数据库管理员临时密码。在最后一行。./mysqld --initialize --user=mysql --datadir=/usr/software/mysql5.7/data --basedir=/usr/software/mysql5.7vi /etc/my.cnf将下面的复制到文件中,然后保存[mysqld] datadir=/usr/software/mysql5.7/data port = 3306 sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES symbolic-links=0 max_connections=400 innodb_file_per_table=1授予my.cnf 配置文件775权限,如下:chmod -R 775 /etc/my.cnf修改/usr/software/mysql5.7/support-files/目录下的mysql.server文件,5个位置的/usr/local/mysql全部修改成/usr/software/mysql5.7。因为没有安装在默认的/usr/local/mysq目录下,所以需要修改成自己安装的路径。启动mysql 服务器1、查询服务ps -ef|grep mysql ps -ef|grep mysqld2、启动服务/usr/software/mysql5.7/support-files/mysql.server start添加软连接,并重启mysql 服务ln -s /usr/software/mysql5.7/support-files/mysql.server /etc/init.d/mysql ln -s /usr/software/mysql5.7/bin/mysql /usr/bin/mysql service mysql restart登录mysql ,密码就是初始化时生成的临时密码mysql -u root -p修改初始密码为自己的密码set password for root@localhost = password('xxxxxxx');开放远程连接use mysql; update user set user.Host='%' where user.User='root'; flush privileges;设置开机自启cp /usr/software/mysql5.7/support-files/mysql.server /etc/init.d/mysqld chmod +x /etc/init.d/mysqld chkconfig --add mysqld chkconfig --list开放3306端口,测试本地客户端是否连接成功打开3306端口firewall-cmd --zone=public --add-port=3306/tcp --permanent配置立即生效firewall-cmd --reload
2023年03月18日
101 阅读
0 评论
0 点赞
2023-03-17
Centos7 编译安装nginx
安装编译开发环境:yum install -y gcc gcc-c++ autoconf automake make安装nginx所需第三方库支持yum install zlib zlib-devel openssl openssl-devel pcre pcre-devel wget httpd-tools vim -y下载安装源码wget http://nginx.org/download/nginx-1.23.3.tar.gz解压缩进入目录tar -zxvf nginx-1.23.3.tar.gz cd nginx-1.23.3开始安装./configure --prefix=/home/soft/nginx make && make install
2023年03月17日
102 阅读
0 评论
0 点赞
2023-03-16
Git冲突:Please commit your changes or stash them before you merge
方法一:放弃本地修改 (此方法本地修改的代码会被丢弃,不可找回)git reset --hard git pullgit reset --hard:撤销工作区中所有未提交的修改内容,将暂存区与工作区都回到上一次版本,并删除之前的所有信息提交方法二:使用git stashgit stash git pull git stash popgit stash:保存当前工作进度,能够将所有未提交的修改(工作区和暂存区)保存至堆栈中,用于后续恢复当前工作目录。也可以用git stash save,作用等同于git stash,区别是可以加一些注释git pull:把服务器仓库的更新拉到本地仓库中git stash pop:可以把你刚才stash到本地栈中的代码pop到本地(也可以用git stash apply,区别:使用apply恢复,stash列表中的信息是会继续保留的,而使用pop恢复,会将stash列表中的信息进行删除。)git stash list:存储到本地栈顶以后,你可以使用git stash list 查看你本地存储的stash日志git stash clear: 清空Git栈,原来stash的节点都会被清除
2023年03月16日
234 阅读
0 评论
0 点赞
2023-03-04
jquery shoplazza 投递时间提示代码
<div class="tw-w-full tw-flex tw-items-center tw-mt-4 product-info__marketing-delivery-time {% if section.settings.delivery_time_show_as_date %}product-info__marketing-delivery-time_date{% endif %}" data-delivery-min="{{section.settings.delivery_time_min}}" data-delivery-max="{{section.settings.delivery_time_max}}" > {% include 'icon_sun_shipping',icon_class:"" %} <span class="tw-ml-2 tw-leading-none" > {% if section.settings.delivery_time_show_as_date %} {{ 'i18n.product.product_detail.marketing_delivery' | t: from: "<b></b>",to:"<b></b>"}}{% else %}{{'i18n.product.product_detail.marketing_delivery_days' | t: from: "<b></b>",to:"<b></b>" }} {% endif %} </span> </div><script> $(function () { var $delivery = $(".product-info__marketing-delivery-time"); if ($delivery.length) { var max = $delivery.attr("data-delivery-max"); var min = $delivery.attr("data-delivery-min"); if ($delivery.is(".product-info__marketing-delivery-time_date")) { var maxdate = new Date((new Date()).getTime() + (max * 86400000)); var mindate = new Date((new Date()).getTime() + (min * 86400000)); var formatter = new Intl.DateTimeFormat('en', { month: 'short', day: "2-digit" }); $delivery.find("b").eq(0).html(formatter.format(mindate)) $delivery.find("b").eq(1).html(formatter.format(maxdate)) } else { $delivery.find("b").eq(0).html(min); $delivery.find("b").eq(1).html(max); } } }); </script>
2023年03月04日
116 阅读
0 评论
1 点赞
2023-02-24
店匠shoplazza获取自定义属性metafields时json格式
假设设置的命名空间为sunshine,属性名为lists,json数据为{ "name": "sunshine", "age": 18 }则在Liquid中,想要获取name值,用product.metafields.sunshine.lists.value.name
2023年02月24日
227 阅读
0 评论
1 点赞
2023-02-16
浏览器滚动条
滚动条,浏览器滚动条,好看的浏览器滚动条
2023年02月16日
84 阅读
0 评论
0 点赞
2023-02-13
details summary 优化版
案例一<style> * { margin: 0; padding: 0; box-sizing: border-box; } ::-webkit-details-marker { display: none; } ::-moz-list-bullet { font-size: 0; float: left; } </style> <style> #container1 { width: 100%; height: 100%; position: relative; overflow: auto; } #container1 .main { width: 90%; margin: auto; } #container1 summary { outline: none; padding: 10px 5px; cursor: pointer; background: #eee; list-style: none; margin-bottom: 2px; font-weight: bold; display: flex; width: 100%; } </style> <div id="container1"> <div class="main"> <details open> <summary onclick="changeOpen(this)" class="open"> <b>-</b> <span>Entry Level</span> </summary> <div class="compare_content"> content1 </div> </details> <details open> <summary onclick="changeOpen(this)" class="open"> <b>-</b><span>Advanced Models</span> </summary> <div class="compare_content"> content2 </div> </details> <details open> <summary onclick="changeOpen(this)" class="open"> <b>-</b> <span>High-Performance</span> </summary> <div class="compare_content"> content3 </div> </details> </div> </div> <script> function changeOpen(obj) { const b = obj.querySelectorAll('b') console.log(obj.className) if (obj.className == 'open') { obj.className = 'close' b[0].innerHTML = '+'; } else if (obj.className == 'close') { b[0].innerHTML = '-'; obj.className = 'open' } if (obj.className == '') { b[0].innerHTML = '-'; obj.className = 'open' } } </script>案例二<style> #container2 div { width: 7%; margin: 0 auto; text-align: center; } #container2 details { position: relative; background: #f5f5f5; } #container2 summary { font-weight: bolder; cursor: pointer; user-select: none; outline: none; display: flex; position: relative; } #container2 li { border: 1px solid #eee; border-top: 0; list-style: none; } /* 实现动画的原理 */ #container2 summary::after { content: ''; width: 0; height: 0; line-height: 0; font-size: 0; border-left: 5px dashed transparent; border-right: 5px dashed transparent; border-top: 5px solid #000; position: absolute; top: 50%; transform: translateY(-50%); right: 1%; transition: .3s ease-out; } #container2 [open] summary::after { transform: translateY(-50%) rotate(180deg); } #container2 ul { padding: 0; margin-top: 0; transition: .3s ease-out; overflow: hidden; } #container2 [open] + ul { /*max-height: 60px;*/ } </style> <div id="container2"> <div> <details open> <summary>商品管理</summary> <ul> <li>商品列表</li> <li>添加商品</li> </ul> </details> </div> <div> <details open> <summary>品牌管理</summary> <ul> <li>品牌列表</li> <li>添加品牌</li> </ul> </details> </div> <div> <details open> <summary>分类管理</summary> <ul> <li>分类列表</li> <li>添加分类</li> </ul> </details> </div> </div>案例三<style> #container3 { margin-top: 50px; } #container3 div { width: 7%; margin: 0 auto; text-align: center; } #container3 details { position: relative; background: #f5f5f5; } #container3 summary { font-weight: bolder; cursor: pointer; user-select: none; outline: none; display: flex; position: relative; } #container3 li { border: 1px solid #eee; border-top: 0; list-style: none; } /* 实现动画的原理 */ #container3 summary::after { content: '+'; font-size: 20px; /*border-left: 5px dashed transparent;*/ /*border-right: 5px dashed transparent;*/ /*border-top: 5px solid #000;*/ position: absolute; top: 50%; transform: translateY(-50%); right: 6px; transition: .3s ease-in; } #container3 [open] summary::after { right: 6px; font-size: 20px; content: '-'; transition: .3s ease-in; } #container3 summary + .content { height: 0; padding: 0; margin-top: 0; overflow: hidden; width: 100%; transition: height 3s; } #container3 [open] summary + .content { height: max-content; width: 100%; } </style> <div id="container3"> <div> <details open> <summary>商品管理</summary> <div class="content"> <ul> <li>商品列表</li> <li>添加商品</li> </ul> </div> </details> </div> <div> <details open> <summary>品牌管理</summary> <div class="content"> <ul> <li>品牌列表</li> <li>添加品牌</li> </ul> </div> </details> </div> <div> <details open> <summary>分类管理</summary> <div class="content"> <ul> <li>分类列表</li> <li>添加分类</li> </ul> </div> </details> </div> </div>案例四<style> #container4 { margin-top: 50px; } #container4 div { width: 7%; margin: 0 auto; text-align: center; } #container4 details { position: relative; background: #f5f5f5; } #container4 summary { font-weight: bolder; cursor: pointer; user-select: none; outline: none; display: flex; position: relative; padding-left: 20px; } #container4 li { border: 1px solid #eee; border-top: 0; list-style: none; } /* 实现动画的原理 */ #container4 summary::after { content: '+'; font-size: 20px; /*border-left: 5px dashed transparent;*/ /*border-right: 5px dashed transparent;*/ /*border-top: 5px solid #000;*/ position: absolute; top: 50%; transform: translateY(-50%); left: 6px; transition: .3s ease-in; } #container4 [open] summary::after { left: 6px; font-size: 20px; content: '-'; transition: .3s ease-in; } #container4 .content { transition: height 3s; } #container4 summary + .content { height: 0; padding: 0; margin-top: 0; overflow: hidden; width: 100%; } #container4 [open] summary + .content { height: max-content; width: 100%; } </style> <div id="container4"> <div> <details open> <summary>商品管理</summary> <div class="content"> <ul> <li>商品列表</li> <li>添加商品</li> </ul> </div> </details> </div> <div> <details open> <summary>品牌管理</summary> <div class="content"> <ul> <li>品牌列表</li> <li>添加品牌</li> </ul> </div> </details> </div> <div> <details open> <summary>分类管理</summary> <div class="content"> <ul> <li>分类列表</li> <li>添加分类</li> </ul> </div> </details> </div> </div>
2023年02月13日
64 阅读
0 评论
1 点赞
2023-02-06
52 条 SQL 语句性能优化策略
1、对查询进行优化,应尽量避免全表扫描,首先应考虑在where及order by涉及的列上建立索引。2、应尽量避免在where子句中对字段进行null值判断,创建表时NULL是默认值,但大多数时候应该使用NOT NULL,或者使用一个特殊的值,如0,-1作为默认值。3、应尽量避免在where子句中使用!=或<>操作符,MySQL只有对以下操作符才使用索引:<,<=,=,>,>=,BETWEEN,IN,以及某些时候的LIKE。4、应尽量避免在where子句中使用or来连接条件,否则将导致引擎放弃使用索引而进行全表扫描,可以使用UNION合并查询:select id from t where num=10 union all select id from t where num=20。5、in和not in也要慎用,否则会导致全表扫描,对于连续的数值,能用between就不要用in了:Select id from t where num between 1 and 3。6、下面的查询也将导致全表扫描:select id from t where name like‘%abc%’或者select id from t where name like‘%abc’若要提高效率,可以考虑全文检索。而select id from t where name like‘abc%’才用到索引。7、如果在where子句中使用参数,也会导致全表扫描。8、应尽量避免在where子句中对字段进行表达式操作,应尽量避免在where子句中对字段进行函数操作。9、很多时候用exists代替in是一个好的选择:select num from a where num in(select num from b)。用下面的语句替换:select num from a where exists(select 1 from b where num=a.num)。10、索引固然可以提高相应的select的效率,但同时也降低了insert及update的效率,因为insert或update时有可能会重建索引,所以怎样建索引需要慎重考虑,视具体情况而定。一个表的索引数最好不要超过6个,若太多则应考虑一些不常使用到的列上建的索引是否有必要。11、应尽可能的避免更新clustered索引数据列, 因为clustered索引数据列的顺序就是表记录的物理存储顺序,一旦该列值改变将导致整个表记录的顺序的调整,会耗费相当大的资源。若应用系统需要频繁更新clustered索引数据列,那么需要考虑是否应将该索引建为clustered索引。12、尽量使用数字型字段,若只含数值信息的字段尽量不要设计为字符型,这会降低查询和连接的性能,并会增加存储开销。13、尽可能的使用varchar/nvarchar代替char/nchar,因为首先变长字段存储空间小,可以节省存储空间,其次对于查询来说,在一个相对较小的字段内搜索效率显然要高些。14、最好不要使用”“返回所有:select from t ,用具体的字段列表代替“*”,不要返回用不到的任何字段。15、尽量避免向客户端返回大数据量,若数据量过大,应该考虑相应需求是否合理。16、使用表的别名(Alias):当在SQL语句中连接多个表时,请使用表的别名并把别名前缀于每个Column上。这样一来,就可以减少解析的时间并减少那些由Column歧义引起的语法错误。17、使用“临时表”暂存中间结果 :简化SQL语句的重要方法就是采用临时表暂存中间结果,但是临时表的好处远远不止这些,将临时结果暂存在临时表,后面的查询就在tempdb中了,这可以避免程序中多次扫描主表,也大大减少了程序执行中“共享锁”阻塞“更新锁”,减少了阻塞,提高了并发性能。18、一些SQL查询语句应加上nolock,读、写是会相互阻塞的,为了提高并发性能,对于一些查询,可以加上nolock,这样读的时候可以允许写,但缺点是可能读到未提交的脏数据。使用nolock有3条原则:查询的结果用于“插、删、改”的不能加nolock;查询的表属于频繁发生页分裂的,慎用nolock ;使用临时表一样可以保存“数据前影”,起到类似Oracle的undo表空间的功能,能采用临时表提高并发性能的,不要用nolock。19、常见的简化规则如下:不要有超过5个以上的表连接(JOIN),考虑使用临时表或表变量存放中间结果。少用子查询,视图嵌套不要过深,一般视图嵌套不要超过2个为宜。20、将需要查询的结果预先计算好放在表中,查询的时候再Select。这在SQL7.0以前是最重要的手段,例如医院的住院费计算。21、用OR的字句可以分解成多个查询,并且通过UNION 连接多个查询。他们的速度只同是否使用索引有关,如果查询需要用到联合索引,用UNION all执行的效率更高。多个OR的字句没有用到索引,改写成UNION的形式再试图与索引匹配。一个关键的问题是否用到索引。22、在IN后面值的列表中,将出现最频繁的值放在最前面,出现得最少的放在最后面,减少判断的次数。23、尽量将数据的处理工作放在服务器上,减少网络的开销,如使用存储过程。存储过程是编译好、优化过、并且被组织到一个执行规划里、且存储在数据库中的SQL语句,是控制流语言的集合,速度当然快。反复执行的动态SQL,可以使用临时存储过程,该过程(临时表)被放在Tempdb中。24、当服务器的内存够多时,配制线程数量 = 最大连接数+5,这样能发挥最大的效率;否则使用 配制线程数量<最大连接数启用SQL SERVER的线程池来解决,如果还是数量 = 最大连接数+5,严重的损害服务器的性能。25、查询的关联同写的顺序 :select a.personMemberID, * from chineseresume a,personmember b where personMemberID = b.referenceid and a.personMemberID = ‘JCNPRH39681’ (A = B ,B = ‘号码’) select a.personMemberID, * from chineseresume a,personmember b where a.personMemberID = b.referenceid and a.personMemberID = ‘JCNPRH39681’ and b.referenceid = ‘JCNPRH39681’ (A = B ,B = ‘号码’, A = ‘号码’) select a.personMemberID, * from chineseresume a,personmember b where b.referenceid = ‘JCNPRH39681’ and a.personMemberID = ‘JCNPRH39681’ (B = ‘号码’, A = ‘号码’) 26、尽量使用exists代替select count(1)来判断是否存在记录,count函数只有在统计表中所有行数时使用,而且count(1)比count(*)更有效率。27、尽量使用“>=”,不要使用“>”。28、索引的使用规范:索引的创建要与应用结合考虑,建议大的OLTP表不要超过6个索引;尽可能的使用索引字段作为查询条件,尤其是聚簇索引,必要时可以通过index index_name来强制指定索引;避免对大表查询时进行table scan,必要时考虑新建索引;在使用索引字段作为条件时,如果该索引是联合索引,那么必须使用到该索引中的第一个字段作为条件时才能保证系统使用该索引,否则该索引将不会被使用;要注意索引的维护,周期性重建索引,重新编译存储过程。 29、下列SQL条件语句中的列都建有恰当的索引,但执行速度却非常慢:SELECT * FROM record WHERE substrINg(card_no,1,4)=’5378’ (13秒) SELECT * FROM record WHERE amount/30< 1000 (11秒) SELECT * FROM record WHERE convert(char(10),date,112)=’19991201’ (10秒) 分析: WHERE子句中对列的任何操作结果都是在SQL运行时逐列计算得到的,因此它不得不进行表搜索,而没有使用该列上面的索引。如果这些结果在查询编译时就能得到,那么就可以被SQL优化器优化,使用索引,避免表搜索,因此将SQL重写成下面这样:SELECT * FROM record WHERE card_no like ‘5378%’ (< 1秒) SELECT * FROM record WHERE amount< 1000*30 (< 1秒) SELECT * FROM record WHERE date= ‘1999/12/01’ (< 1秒)30、当有一批处理的插入或更新时,用批量插入或批量更新,绝不会一条条记录的去更新。31、在所有的存储过程中,能够用SQL语句的,我绝不会用循环去实现。例如:列出上个月的每一天,我会用connect by去递归查询一下,绝不会去用循环从上个月第一天到最后一天。32、选择最有效率的表名顺序(只在基于规则的优化器中有效): Oracle的解析器按照从右到左的顺序处理FROM子句中的表名,FROM子句中写在最后的表(基础表 driving table)将被最先处理,在FROM子句中包含多个表的情况下,你必须选择记录条数最少的表作为基础表。如果有3个以上的表连接查询,那就需要选择交叉表(intersection table)作为基础表,交叉表是指那个被其他表所引用的表。33、提高GROUP BY语句的效率,可以通过将不需要的记录在GROUP BY之前过滤掉。下面两个查询返回相同结果,但第二个明显就快了许多。 低效:SELECT JOB , AVG(SAL) FROM EMP GROUP BY JOB HAVING JOB =’PRESIDENT’ OR JOB =’MANAGER’ 高效:SELECT JOB , AVG(SAL) FROM EMP WHERE JOB =’PRESIDENT’ OR JOB =’MANAGER’ GROUP BY JOB34、SQL语句用大写,因为Oracle总是先解析SQL语句,把小写的字母转换成大写的再执行。35、别名的使用,别名是大型数据库的应用技巧,就是表名、列名在查询中以一个字母为别名,查询速度要比建连接表快1.5倍。36、避免死锁,在你的存储过程和触发器中访问同一个表时总是以相同的顺序;事务应经可能地缩短,在一个事务中应尽可能减少涉及到的数据量;永远不要在事务中等待用户输入。37、避免使用临时表,除非却有需要,否则应尽量避免使用临时表,相反,可以使用表变量代替;大多数时候(99%),表变量驻扎在内存中,因此速度比临时表更快,临时表驻扎在TempDb数据库中,因此临时表上的操作需要跨数据库通信,速度自然慢。38、最好不要使用触发器:触发一个触发器,执行一个触发器事件本身就是一个耗费资源的过程;如果能够使用约束实现的,尽量不要使用触发器;不要为不同的触发事件(Insert,Update和Delete)使用相同的触发器;不要在触发器中使用事务型代码。39、索引创建规则: 表的主键、外键必须有索引; 数据量超过300的表应该有索引; 经常与其他表进行连接的表,在连接字段上应该建立索引; 经常出现在Where子句中的字段,特别是大表的字段,应该建立索引; 索引应该建在选择性高的字段上; 索引应该建在小字段上,对于大的文本字段甚至超长字段,不要建索引; 复合索引的建立需要进行仔细分析,尽量考虑用单字段索引代替; 正确选择复合索引中的主列字段,一般是选择性较好的字段; 复合索引的几个字段是否经常同时以AND方式出现在Where子句中?单字段查询是否极少甚至没有?如果是,则可以建立复合索引;否则考虑单字段索引; 如果复合索引中包含的字段经常单独出现在Where子句中,则分解为多个单字段索引; 如果复合索引所包含的字段超过3个,那么仔细考虑其必要性,考虑减少复合的字段; 如果既有单字段索引,又有这几个字段上的复合索引,一般可以删除复合索引; 频繁进行数据操作的表,不要建立太多的索引; 删除无用的索引,避免对执行计划造成负面影响; 表上建立的每个索引都会增加存储开销,索引对于插入、删除、更新操作也会增加处理上的开销。另外,过多的复合索引,在有单字段索引的情况下,一般都是没有存在价值的;相反,还会降低数据增加删除时的性能,特别是对频繁更新的表来说,负面影响更大。 尽量不要对数据库中某个含有大量重复的值的字段建立索引。40、MySQL查询优化总结:使用慢查询日志去发现慢查询,使用执行计划去判断查询是否正常运行,总是去测试你的查询看看是否他们运行在最佳状态下。久而久之性能总会变化,避免在整个表上使用count(*),它可能锁住整张表,使查询保持一致以便后续相似的查询可以使用查询缓存,在适当的情形下使用GROUP BY而不是DISTINCT,在WHERE、GROUP BY和ORDER BY子句中使用有索引的列,保持索引简单,不在多个索引中包含同一个列。有时候MySQL会使用错误的索引,对于这种情况使用USE INDEX,检查使用SQL_MODE=STRICT的问题,对于记录数小于5的索引字段,在UNION的时候使用LIMIT不是是用OR。 为了避免在更新前SELECT,使用INSERT ON DUPLICATE KEY或者INSERT IGNORE,不要用UPDATE去实现,不要使用MAX,使用索引字段和ORDER BY子句,LIMIT M,N实际上可以减缓查询在某些情况下,有节制地使用,在WHERE子句中使用UNION代替子查询,在重新启动的MySQL,记得来温暖你的数据库,以确保数据在内存和查询速度快,考虑持久连接,而不是多个连接,以减少开销。基准查询,包括使用服务器上的负载,有时一个简单的查询可以影响其他查询,当负载增加在服务器上,使用SHOW PROCESSLIST查看慢的和有问题的查询,在开发环境中产生的镜像数据中测试的所有可疑的查询。41、MySQL备份过程:从二级复制服务器上进行备份;在进行备份期间停止复制,以避免在数据依赖和外键约束上出现不一致;彻底停止MySQL,从数据库文件进行备份;如果使用MySQL dump进行备份,请同时备份二进制日志文件 – 确保复制没有中断;不要信任LVM快照,这很可能产生数据不一致,将来会给你带来麻烦;为了更容易进行单表恢复,以表为单位导出数据——如果数据是与其他表隔离的。 当使用mysqldump时请使用–opt;在备份之前检查和优化表;为了更快的进行导入,在导入时临时禁用外键约束。;为了更快的进行导入,在导入时临时禁用唯一性检测;在每一次备份后计算数据库,表以及索引的尺寸,以便更够监控数据尺寸的增长;通过自动调度脚本监控复制实例的错误和延迟;定期执行备份。42、查询缓冲并不自动处理空格,因此,在写SQL语句时,应尽量减少空格的使用,尤其是在SQL首和尾的空格(因为查询缓冲并不自动截取首尾空格)。43、member用mid做标准进行分表方便查询么?一般的业务需求中基本上都是以username为查询依据,正常应当是username做hash取模来分表。而分表的话MySQL的partition功能就是干这个的,对代码是透明的;在代码层面去实现貌似是不合理的。44、我们应该为数据库里的每张表都设置一个ID做为其主键,而且最好的是一个INT型的(推荐使用UNSIGNED),并设置上自动增加的AUTO_INCREMENT标志。45、在所有的存储过程和触发器的开始处设置SET NOCOUNT ON,在结束时设置SET NOCOUNT OFF。无需在执行存储过程和触发器的每个语句后向客户端发送DONE_IN_PROC消息。46、MySQL查询可以启用高速查询缓存。这是提高数据库性能的有效MySQL优化方法之一。当同一个查询被执行多次时,从缓存中提取数据和直接从数据库中返回数据快很多。47、EXPLAIN SELECT查询用来跟踪查看效果:使用EXPLAIN关键字可以让你知道MySQL是如何处理你的SQL语句的。这可以帮你分析你的查询语句或是表结构的性能瓶颈。EXPLAIN的查询结果还会告诉你你的索引主键被如何利用的,你的数据表是如何被搜索和排序的。48、当只要一行数据时使用LIMIT 1 :当你查询表的有些时候,你已经知道结果只会有一条结果,但因为你可能需要去fetch游标,或是你也许会去检查返回的记录数。在这种情况下,加上LIMIT 1可以增加性能。这样一来,MySQL数据库引擎会在找到一条数据后停止搜索,而不是继续往后查少下一条符合记录的数据。49、选择表合适存储引擎: myisam:应用时以读和插入操作为主,只有少量的更新和删除,并且对事务的完整性,并发性要求不是很高的。 InnoDB:事务处理,以及并发条件下要求数据的一致性。除了插入和查询外,包括很多的更新和删除。(InnoDB有效地降低删除和更新导致的锁定)。对于支持事务的InnoDB类型的表来说,影响速度的主要原因是AUTOCOMMIT默认设置是打开的,而且程序没有显式调用BEGIN 开始事务,导致每插入一条都自动提交,严重影响了速度。可以在执行SQL前调用begin,多条SQL形成一个事物(即使autocommit打开也可以),将大大提高性能。50、优化表的数据类型,选择合适的数据类型: 原则:更小通常更好,简单就好,所有字段都得有默认值,尽量避免null。 例如:数据库表设计时候更小的占磁盘空间尽可能使用更小的整数类型。(mediumint就比int更合适) 比如时间字段:datetime和timestamp,datetime占用8个字节,而timestamp占用4个字节,只用了一半,而timestamp表示的范围是1970—2037适合做更新时间 MySQL可以很好的支持大数据量的存取,但是一般说来,数据库中的表越小,在它上面执行的查询也就会越快。 因此,在创建表的时候,为了获得更好的性能,我们可以将表中字段的宽度设得尽可能小。例如:在定义邮政编码这个字段时,如果将其设置为CHAR(255),显然给数据库增加了不必要的空间。甚至使用VARCHAR这种类型也是多余的,因为CHAR(6)就可以很好的完成任务了。同样的,如果可以的话,我们应该使用MEDIUMINT而不是BIGIN来定义整型字段,应该尽量把字段设置为NOT NULL,这样在将来执行查询的时候,数据库不用去比较NULL值。 对于某些文本字段,例如“省份”或者“性别”,我们可以将它们定义为ENUM类型。因为在MySQL中,ENUM类型被当作数值型数据来处理,而数值型数据被处理起来的速度要比文本类型快得多。这样,我们又可以提高数据库的性能。51、字符串数据类型:char,varchar,text选择区别。52、任何对列的操作都将导致表扫描,它包括数据库函数、计算表达式等等,查询时要尽可能将操作移至等号右边。
2023年02月06日
84 阅读
0 评论
0 点赞
2023-01-14
Shopify Blog Listing Code
<aside> {%- if section.settings.blog_show_tags -%} <ul> <li> {%- for tag in blog.all_tags -%} <a href="{{ blog.url }}/tagged/{{ tag | handle }}">{{ tag }}</a>{% unless forloop.last %}, {% endunless %} {%- endfor -%} </li> </ul> {%- endif -%} </aside> {% schema %} { "name": "Blog posts", "settings": [ { "type": "checkbox", "id": "blog_show_tags", "label": "Show tags", "default": true } ] } {% endschema %}
2023年01月14日
63 阅读
0 评论
1 点赞
2022-12-24
Vue3 学习笔记(七)
02-详解接口与类型别名之间区别03-字面量类型和keyof关键字04-类型保护与自定义类型保护05-定义泛型和泛型常见操作06-类型兼容性详解07-映射类型与内置工具类型08-条件类型和infer关键字09-类中如何使用类型详解接口与类型别名之间区别接口接口是一系列抽象方法的声明,是一些方法特征的集合。简单来说,接口的作用就是为这些类型命名和为你的代码或第三方代码定义契约。接口跟类型别名类似都是用来定义类型注解的,接口是用interface关键字来实现的,如下:interface A { username: string; age: number; } let a: A = { username: 'xiaoming', age: 20 }因为接口跟类型别名功能类似,所以接口也具备像索引签名,可调用注解等功能。interface A { [index: number]: number; } let a: A = [1, 2, 3]; interface A { (): void; } let a: A = () => {}接口与别名的区别那么接口跟类型别名除了很多功能相似外,他们之间也是具备某些区别的。对象类型接口合并接口继承映射类型第一个区别,类型别名可以操作任意类型,而接口只能操作对象类型。第二个区别,接口可以进行合并操作。interface A { username: string; } interface A { age: number; } let a: A = { username: 'xiaoming', age: 20 }第三个区别,接口具备继承能力。interface A { username: string } interface B extends A { age: number } let b: B = { username: 'xiaoming', age: 20 }B这个接口继承了A接口,所以B类型就有了username这个属性。在指定类型的时候,b变量要求同时具备A类型和B类型。第四个区别,接口不具备定义成接口的映射类型,而别名是可以做成映射类型的,关于映射类型的用法后面小节中会详细的进行讲解,这里先看一下效果。type A = { // success [P in 'username'|'age']: string; } interface A { // error [P in 'username'|'age']: string; }字面量类型和keyof关键字字面量类型在TS中可以把字面量作为具体的类型来使用,当使用字面量作为具体类型时, 该类型的取值就必须是该字面量的值。type A = 1; let a: A = 1;这里的A对应一个1这样的值,所以A类型就是字面量类型,那么a变量就只能选择1作为可选的值,除了1作为值以外,那么其他值都不能赋值给a变量。那么字面量类型到底有什么作用呢?实际上字面量类型可以把类型进行缩小,只在指定的范围内生效,这样可以保证值不易写错。type A = 'linear'|'swing'; let a: A = 'ease' // error比如a变量,只有两个选择,要么是linear要么是swing,不能是其他的第三个值作为选项存在。keyof关键字在一个定义好的接口中,想把接口中的每一个属性提取出来,形成一个联合的字面量类型,那么就可以利用keyof关键字来实现。interface A { username: string; age: number; } //keyof A -> 'username'|'age' let a: keyof A = 'username';如果我们利用typeof语法去引用一个变量,可以得到这个变量所对应的类型,如下:let a = 'hello'; type A = typeof a; // string 那么利用这样一个特性,可以通过一个对象得到对应的字面量类型,把typeof和keyof两个关键字结合使用。let obj: { username: 'xiaoming', age: 20 } let a: keyof typeof obj = 'username'类型保护与自定义类型保护类型保护类型保护允许你使用更小范围下的对象类型。这样可以缩小类型的范围保证类型的正确性,防止TS报错。这段代码在没有类型保护的情况下就会报错,如下:function foo(n: string|number){ n.length // error }因为n有可能是number,所以TS会进行错误提示,可以利用类型断言来解决,但是这种方式只是欺骗TS,如果在运行阶段还是可能报错的,所以并不是最好的方式。利用类型保护可以更好的解决这个问题。类型保护的方式有很多种,主要是四种方式:typeof关键字instanceof关键字in关键字字面量类型typeof关键字实现类型保护:function foo(n: string|number){ if(typeof n === 'string'){ n.length // success } }instanceof关键字实现类型保护,主要是针对类进行保护的:class Foo { username = 'xiaoming' } class Bar { age = 20 } function baz(n: Foo|Bar){ if( n instanceof Foo ){ n.username } }in关键字实现类型保护,主要是针对对象的属性保护的:function foo(n: { username: string } | { age: number }){ if( 'username' in n ){ n.username } }字面量类型保护,如下:function foo(n: 'username'|123){ if( n === 'username' ){ n.length } }自定义类型保护除了以上四种方式可以做类型保护外,如果我们想自己去实现类型保护可行吗?答案是可以的,只需要利用is关键字即可, is为类型谓词,它可以做到类型保护。function isString(n: any): n is string{ return typeof n === 'string'; } function foo(n: string|number){ if( isString(n) ){ n.length } }定义泛型和泛型常见操作定义泛型泛型是指在定义函数、接口或者类时,未指定其参数类型,只有在运行时传入才能确定。泛型简单来说就是对类型进行传参处理。type A<T = string> = T //泛型默认值 let a: A = 'hello' let b: A<number> = 123 let c: A<boolean> = true这里可以看到通过<T>来定义泛型,还可以给泛型添加默认值<T=string>,这样当我们不传递类型的时候,就会已string作为默认的类型进行使用。泛型还可以传递多个,实现多泛型的写法。type A<T, U> = T|U; //多泛型在前面我们学习数组的时候,讲过数组有两种定义方式,除了基本定义外,还有一种泛型的写法,如下:let arr: Array<number> = [1, 2, 3]; //自定义MyArray实现 type MyArray<T> = T[]; let arr2: MyArray<number> = [1, 2, 3];泛型在函数中的使用:function foo<T>(n: T){ } foo<string>('hello'); foo(123); // 泛型会自动类型推断泛型跟接口结合的用法:interface A<T> { (n?: T): void default?: T } let foo: A<string> = (n) => {} let foo2: A<number> = (n) => {} foo('hello') foo.default = 'hi' foo2(123) foo2.default = 123泛型与类结合的用法:class Foo<T> { username!: T; } let f = new Foo<string>(); f.username = 'hello'; class Foo<T> { username!: T } class Baz extends Foo<string> {} let f = new Baz() f.username = 'hello'有时候也会对泛型进行约束,可以指定哪些类型才能进行传递:type A = { length: number } function foo<T extends A>(n: T) {} foo(123) // error foo('hello')通过extends关键字可以完成泛型约束处理。类型兼容性详解类型兼容性类型兼容性用于确定一个类型是否能赋值给其他类型。如果是相同的类型是可以进行赋值的,如果是不同的类型就不能进行赋值操作。let a: number = 123; let b: number = 456; b = a; // success let a: number = 123; let b: string = 'hello'; b = a; // error当有类型包含的情况下,又是如何处理的呢?let a: number = 123; let b: string | number = 'hello'; //b = a; // success a = b; // error变量a是可以赋值给变量b的,但是变量b是不能赋值给变量a的,因为b的类型包含a的类型,所以a赋值给b是可以的。在对象类型中也是一样的处理方式,代码如下:let a: {username: string} = { username: 'xiaoming' }; let b: {username: string; age: number} = { username: 'xiaoming', age: 20 }; a = b; // success b = a; // errorb的类型满足a的类型,所以b是可以赋值给a的,但是a的类型不能满足b的类型,所以a不能赋值给b。所以看下面的例子就明白为什么这样操作是可以的。function foo(n: { username: string }) {} foo({ username: 'xiaoming' }) // success foo({ username: 'xiaoming', age: 20 }) // error let a = { username: 'xiaoming', age: 20 } foo(a) // success这里把值存成一个变量a,再去进行传参就是利用了类型兼容性做到的。映射类型与内置工具类型映射类型可以将已知类型的每个属性都变为可选的或者只读的。简单来说就是可以从一种类型映射出另一种类型。这里我们先要明确一点,映射类型只能用类型别名去实现,不能使用接口的方式来实现。先看一下在TS中是如何定义一个映射类型的。type A = { username: string age: number } type B<T> = { [P in keyof T]: T[P] } type C = B<A>这段代码中类型C与类型A是完全一样的,其中in关键字就类似于一个for in循环,可以处理A类型中的所有属性记做p,然后就可以得到对应的类型T[p]。那么我们就可以通过添加一些其他语法来实现不同的类型出来,例如让每一个属性都是只读的,可以给每一项前面添加readonly关键字。type B<T> = { readonly [P in keyof T]: T[P] }内置工具类型每次我们去实现这种映射类型的功能是非常麻烦的,所以TS中给我们提供了很多常见的映射类型,这些内置的映射类型被叫做,内置工具类型。Readonly就是跟我们上边实现的映射类型是一样的功能,给每一个属性做成只读的。type A = { username: string age: number } /* type B = { readonly username: string; readonly age: number; } */ type B = Readonly<A>Partial可以把每一个属性变成可选的。type A = { username: string age: number } /* type B = { username?: string|undefined; age?: number|undefined; } */ type B = Partial<A>Pick可以把某些指定的属性给筛选出来。type A = { username: string age: number gender: string } /* type D = { username: string; age: number; } */ type D = Pick<A, 'username'|'age'>Record可以把字面量类型指定为统一的类型。/* type E = { username: string; age: string; } */ type E = Record<'username'|'age', string>Required可以把对象的每一个属性变成必选项。type A = { username?: string age?: number } /* type B = { username: string; age: number; } */ type B = Required<A>Omit是跟Pick工具类相反的操作,把指定的属性进行排除。type A = { username: string age: number gender: string } /* type D = { gender: string } */ type D = Omit<A, 'username'|'age'>Exclude可以排除某些类型,得到剩余的类型。// type A = number type A = Exclude<string | number | boolean, string | boolean>我们的内置工具类型还有一些,如:Extract、NonNullable、Parameters、ReturnType等,下一个小节中将继续学习剩余的工具类型。条件类型和infer关键字在上一个小节中,学习了Exclude这个工具类型,那么它的底层实现原理是怎样的呢?type Exclude<T, U> = T extends U ? never : T;这里可以看到Exclude利用了 ? : 的写法来实现的,这种写法在TS类型中表示条件类型,让我们一起来了解下吧。条件类型条件类型就是在初始状态并不直接确定具体类型,而是通过一定的类型运算得到最终的变量类型。type A = string type B = number | string type C = A extends B ? {} : []条件类型需要使用extends关键字,如果A类型继承B类型,那么C类型得到问号后面的类型,如果A类型没有继承B类型,那么C类型得到冒号后面的类型,当无法确定A是否继承B的时候,则返回两个类型的联合类型。那么大多数情况下,条件类型还是在内置工具类型中用的比较多,就像上面的Exclude方法,下面就让我们一起看一下其他内置工具类型该如何去用吧。Extract跟Exclude正好相反,得到需要筛选的类型。// type Extract<T, U> = T extends U ? T : never -> 实现原理 // type A = string type A = Extract<string | number | boolean, string>NonNullable用于排除null和undefined这些类型。//type NonNullable<T> = T extends null | undefined ? never : T; -> 实现原理 //type A = string type A = NonNullable<string|null|undefined>Parameters可以把函数的参数转成对应的元组类型。type Foo = (n: number, m: string) => string //type Parameters<T extends (...args: any) => any> = T extends (...args: infer P) => any ? P : never; -> 实现原理 // type A = [n: number, m: string] type A = Parameters<Foo> 在Parameters方法的实现原理中,出现了一个infer关键字,它主要是用于在程序中对类型进行定义,通过得到定义的p类型来决定最终要的结果。ReturnType可以把函数的返回值提取出类型。type Foo = (n: number, m: string) => string //type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any; -> 实现原理 //type A = string type A = ReturnType<Foo>这里也通过infer关键字定义了一个R类型,对应的就是函数返回值的类型。通过infer关键字可以在泛型之外也可以定义类型出来。下面再利用infer来实现一个小功能,定义一个类型方法,当传递一个数组的时候返回子项的类型,当传递一个基本类型的时候就返回这个基本类型。type A<T> = T extends Array<infer U> ? U : T // type B = number type B = A<Array<number>> // type C = string type C = A<string>这里的U就是自动推断出的数组里的子元素类型,那么就可以完成我们的需求。类中如何使用类型本小节主要讲解在类中如何使用TS的类型,对于类的一些功能使用方式,例如:类的修饰符、混入、装饰器、抽象类等等并不做过多的介绍。类中定义类型属性必须给初始值,如果不给初始值可通过非空断言来解决。class Foo { username!: string; }给初始值的写法如下:class Foo { //第一种写法 //username: string = 'xiaoming'; //第二种写法 // username: string; // constructor(){ // this.username = 'xiaoming'; // } //第三种写法 username: string; constructor(username: string){ this.username = username; } }类中定义方法及添加类型也是非常简单的。class Foo { ... showAge = (n: number): number => { return n; } }类使用接口类中使用接口,是需要使用implements关键字。interface A { username: string age: number showName(n: string): string } class Foo implements A { username: string = 'xiaoming' age: number = 20 gender: string = 'male' showName = (n: string): string => { return n } }在类中使用接口的时候,是一种类型兼容性的方式,对于少的字段是不行的,但是对于多出来的字段是没有问题的,比如说gender字段。类使用泛型class Foo<T> { username: T; constructor(username: T){ this.username = username; } } new Foo<string>('xiaoming');继承中用的也比较多。class Foo<T> { username: T; constructor(username: T){ this.username = username; } } class Bar extends Foo<string> { }最后来看一下,类中去结合接口与泛型的方式。interface A<T> { username: T age: number showName(n: T): T } class Foo implements A<string> { username: string = 'xiaoming' age: number = 20 gender: string = 'male' showName = (n: string): string => { return n } }了解类型中接口与类型别名之间的区别,及各种使用方式掌握什么是泛型与泛型的应用场景,以及与其他语法的结合使用了解了类型的一些高级用法,如:类型保护、类型兼容性了解了类型的一些高级语法,如:映射类型、条件类型全面学习TS中内置的工具类型,如: Partial、Readonly …等
2022年12月24日
48 阅读
0 评论
0 点赞
1
...
10
11
12
...
17