当前位置: 首页 > 编程日记 > 正文

程序员硬核“年终大扫除”,清理了数据库 70GB 空间

作者 | Haki Benita

编译 | 伍杏玲

出品 | AI科技大本营(ID:rgznai100)

【导语】春节将至,俗话说“腊月二十四,掸尘扫房子”,很多人会在腊月二十四给家里做大扫除迎新春。

近年来数据呈爆发式增长,你是否和本文作者一样,常常收到数据库空间的告警呢?那来给数据库做一场“大扫除”试试看?

作者讲述亲身经历,在没有删除单个索引或删除任何数据下,最终释放了超过70GB的未优化和未利用的空间,还意外释放 20GB 未使用索引空间。

咱们一起看看他是如何做到的:

每隔几个月,我都会收到数据库即将用完空间的报警。一般我看到报警后,就再增加一些存储空间,不会多投入精力在那。

但这次我们想给数据库来一次“大扫除”,效果惊人:在没有删除单个索引或删除任何数据下,最终释放了超过 70GB 的未优化和未利用的空间!还有清除了额外的 20GB 未使用的索引值!

这是其中一个数据库的释放存储的图:

删除未被使用过的索引

未被使用的索引是一把“双刃剑”。我们创建它的本意是为了让搜索更快,但它也占用一定的空间,将会影响新增和更新的速度。所以没被使用的索引是我们在清除存储首先要检查的。

查找未使用的索引:

SELECTrelname,indexrelname,idx_scan,idx_tup_read,idx_tup_fetch,pg_size_pretty(pg_relation_size(indexrelname::regclass)) as size
FROMpg_stat_all_indexes
WHEREschemaname = 'public'AND indexrelname NOT LIKE 'pg_toast_%'AND idx_scan = 0AND idx_tup_read = 0AND idx_tup_fetch = 0
ORDER BYsize DESC;

这个查询语句是查找自上次重置统计信息以来,未被扫描或获取的索引。

有一些索引看起来没有被使用,但实际上已被使用了:

  • 可参考:https://www.postgresql.org/docs/current/monitoring-stats.html#MONITORING-PG-STAT-ALL-INDEXES-VIEW

  • 用那些有一定的时间没更新的表里唯一或主键约束的索引。这些索引看起来好像没有被使用过,但我们也不能随意处置它们。

在实际找这些可删除的未使用的索引时,刚开始很耗时耗力,需要很多思考和决策的。

在这过程中,我发现在检查完列表后,重置统计信息计数器是个好方法。PostgreSQL 提供了一些功能来重置不同级别的统计信息。当我发现“疑似”未使用的索引时,或者添加新索引代替旧索引时,通常会重置表的计数器并等待一段时间:

-- Find table oid by name
SELECT oid FROM pg_class c WHERE relname = 'table_name';
-- Reset counts for all indexes of table
SELECT pg_stat_reset_single_table_counters(14662536);

我们每隔一段时间执行一次上述操作来看看有没有要删除的未使用索引。


索引和表格

当我们在更新表中的行时,通常 PostgreSQL 将元组标记为无效,并在下一个可用空间中添加更新的元组,此过程将创建“bloat”,可能会导致表消耗超出实际所需的空间,因此我们需要清除索引bloat。

那我们需要重建索引,PostgreSQL提供了一种使用REINDEX命令就地重建现有索引的方法,无需自己删除和创建索引(https://www.postgresql.org/docs/current/sql-reindex.html):

REINDEX INDEX index_name;

同时重建索引:先前的方法将在表上获得一个锁,防止在操作进行时更改,这似乎不大好使,如果在不锁定索引下重建索引的话,可以同时重建索引:

REINDEX INDEX CONCURRENTLY index_name;

使用 REINDEX CONCURRENTLY 时,PostgreSQL将创建一个名称后缀为“_ccnew”的新索引,并同步对该表更改。重建完成后,它将用新索引切换旧索引,并删除旧索引。

如果由于某种原因你不得不在中间停止重建,也不会删除新索引,它将处于无效状态并占用空间。为了识别在这些无效索引REINDEX,可使用以下查询:

SELECTc.relname as index_name,pg_size_pretty(pg_relation_size(c.oid))
FROMpg_index iJOIN pg_class c ON i.indexrelid = c.oid
WHERE-- New index built using REINDEX CONCURRENTLYc.relname LIKE  '%_ccnew'-- In INVALID stateAND NOT indisvalid
LIMIT 10;

一旦重建过程没有其他执行,应该可以安全删除所有剩余的无效索引。

激活 B 树索引 Deduplication

PostgreSQL 13引入了一种在B树索引存储重复值的新方法,称为“B树 Deduplication”(重复数据删除)。

对于每个索引值,B树索引将在其叶中同时保留值和指向行的指针(TID)。索引值越大,索引越大。PostgreSQL 12 当索引包含许多重复值时,这些重复值将存储在索引叶中。如此一来,将占用很多空间。

从PostgreSQL 13开始,将 B树Deduplication后,重复值仅存储一次,这对具有许多重复值的索引的大小产生影响。

在PostgreSQL 13中,索引 Deduplication 默认情况下处于启用状态:

-- Activating de-deduplication for a B-Tree index, this is the default:
CREATE INDEX index_name ON table_name(column_name) WITH (deduplicate_items = ON)

如果要从PostgreSQL 13 之前的版本迁移的话,需要使用 REINDEX 命令来重建索引,来充分利用索引去重复项的优势。

为了说明 B树 Deduplication 对索引大小的影响,可创建一个包含唯一列和非唯一列的表,填充1M行。在每列上创建两个B树索引,一个启用 Deduplication,另一个禁用 Deduplication:

db=# CREATE test_btree_dedup (n_unique serial, n_not_unique integer);
CREATE TABLEdb=# INSERT INTO test_btree_dedup (n_not_unique)
SELECT (random() * 100)::int FROM generate_series(1, 1000000);
INSERT 0 1000000db=# CREATE INDEX ix1 ON test_btree_dedup (n_unique)     WITH (deduplicate_items = OFF);
CREATE INDEXdb=# CREATE INDEX ix2 ON test_btree_dedup (n_unique)     WITH (deduplicate_items = ON);
CREATE INDEXdb=# CREATE INDEX ix3 ON test_btree_dedup (n_not_unique) WITH (deduplicate_items = OFF);
CREATE INDEXdb=# CREATE INDEX ix4 ON test_btree_dedup (n_not_unique) WITH (deduplicate_items = ON);
CREATE INDEX

我们比较下四个索引的大小:

可以看到,Deduplication对唯一索引没有影响,但对有重复值的索引却有重大影响。不巧的是,由于当时 PostgreSQL 13 刚推出,我们的云提供商未提供支持,因此我没使用Deduplication来清除空间。

清除表中的Bloat

就像在索引中一样,表也可能包含死元组,可能会导致碎片化。与包含关联表中数据的索引不同,不能仅简单地重新创建表。要重新创建表,必须创建一个新表,迁移数据,同步数据,在其他表中创建所有索引……等完成这操作后,才能将旧表切换为新表。

有几种方法可以重建表:

  1. 重新创建表:如上所述,使用这种方法通常需要大量的开发工作,尤其是在重建正在使用表的情况下。

  2. 清理表:PostgreSQL 提供 VACUUM FULL 命令回收表中死元组占用的空间的方法(https://www.postgresql.org/docs/current/sql-vacuum.html)

-- Will lock the table
VACUUM FULL table_name;

上面两种方法需要大量的精力或需要停机一段时间,这两种用于重建表的内置选项都不理想。

使用pg_repack

pg_repack 是一种在不停机的情况下重建表和索引较好的解决方案。创建扩展名来使用pg_repack:

CREATE EXTENSION pg_repack;

rebuild 表和索引:

$ pg_repack -k --table table_name db_name

为了在不停机的情况下重建表,该扩展程序将创建一个新表,将原始表中的数据加载到该表中,同时使其与新数据保持最新,然后再重建索引。该过程完成后,将切换两个表并删除原始表:https://reorg.github.io/pg_repack/#details

使用pg_repack重建表时注意两点:

  • 所需的存储量大约为要重建表的容量:该扩展会创建另一个表来将数据复制到该表,因此它需要的附加存储量约为表及其索引的大小。

  • 可能需要手动清理:如果rebuild过程失败或手动停止,可能会留下一些东向西,需手动清理。

在不停机 pg_repack 下重建表和索引,需额外的存储空间才能运行,所以当你已经没有存储空间时,这不是一个好选择。你需要先检查看看是否有可用的存储空间。

继续清除

看到这,我们已经使用了所有的常规技术来清理了很多空间,但是……还有更多的空间可以删除!重建索引后,在查看索引大小时,有件趣事引起我们注意。

我们其中较大的表是存储交易数据:用户付款后,可选择取消退款。这种情况很少发生,只有一小部分交易被取消。

在这个交易表,既有购买用户又有取消用户的外键,并且每个字段都定义了一个B树索引。采购用户对此具有 NOT NULL 约束,因此所有行均具有值。另一方面,取消用户可以为空,只有一小部分行保存任何数据,取消用户字段中的大多数值均为NULL。

我们希望取消用户的索引比购买用户的索引小得多,但原来它们是完全相同的。之前我总是被教导说 NULL 不被索引,但是在PostgreSQL中却被索引!这个“ Aha”时刻让我们意识到,之前无缘无故写了许多不必要的索引值。

这是我们为取消用户提供的原始索引:

CREATE INDEX transaction_cancelled_by_ix ON transactions(cancelled_by_user_id);

下面用不包含空值的部分索引替换了索引:

DROP INDEX transaction_cancelled_by_ix;CREATE INDEX transaction_cancelled_by_part_ix ON transactions(cancelled_by_user_id)
WHERE cancelled_by_user_id IS NOT NULL;

重新索引后的完整索引大小为769MB,空值超过99%。排除空值的部分索引小于5MB,减少了该指标的 99% 以上!

为了确保不需要这些 NULL 值,我们重置了表上的统计信息,等了一段时间后,我们发现索引的使用就像旧索引一样!我们仅削减了超过 760MB 的未使用索引元组,并没有影响性能!

利用部分索引

一旦我们尝到了局部索引的“甜头”后,我们就会发现还会有更多这样的索引。为了找到他们,我们写了一个查询来搜索具有high字段的索引null_frac,PostgreSQL估计的列值百分比为NULL:

-- Find indexed columns with high null_frac
SELECTc.oid,c.relname AS index,pg_size_pretty(pg_relation_size(c.oid)) AS index_size,i.indisunique AS unique,a.attname AS indexed_column,CASE s.null_fracWHEN 0 THEN ''ELSE to_char(s.null_frac * 100, '999.00%')END AS null_frac,pg_size_pretty((pg_relation_size(c.oid) * s.null_frac)::bigint) AS expected_saving-- Uncomment to include the index definition--, ixs.indexdefFROMpg_class cJOIN pg_index i ON i.indexrelid = c.oidJOIN pg_attribute a ON a.attrelid = c.oidJOIN pg_class c_table ON c_table.oid = i.indrelidJOIN pg_indexes ixs ON c.relname = ixs.indexnameLEFT JOIN pg_stats s ON s.tablename = c_table.relname AND a.attname = s.attnameWHERE-- Primary key cannot be partialNOT i.indisprimary-- Exclude already partial indexesAND i.indpred IS NULL-- Exclude composite indexesAND array_length(i.indkey, 1) = 1-- Larger than 10MBAND pg_relation_size(c.oid) > 10 * 1024 ^ 2ORDER BYpg_relation_size(c.oid) * s.null_frac DESC;

查询结果为:

  • tx_cancelled_by_ix 是具有许多空值的大型索引:此处潜力巨大!

  • tx_op_1_ix 是大索引,几乎没有空值:潜力不大

  • tx_token_ix 是带有少量空值的小索引:不管它

  • tx_op_name_ix 是没有空值的大索引:没啥用

结果表明,通过将tx_cancelled_by_ix变成不包含null的部分索引,可节省约1.3GB。

从索引中排除空值是否总是有好处?NULL和任何其他值一样有意义。如果查询使用了 IS NULL,这些查询可能会受益于索引NULL。

这个方法仅对空值有用?使用部分索引排除不经常查询或根本不查询的值可能有益于任何值,而不仅仅是空值。NULL通常表示缺少值,我们没有很多查询在搜索空值,因此将它们从索引中排除是有意义的。

你最终如何清除超过20GB的空间呢?你可能已经注意到,上文提到了超过20GB的可用空间,但是图表仅显示一半,那就将索引从复制中删除!从主数据库释放10GB时,每个副本的存储量也大致相同。


Django ORM迁移

为了将上述技术与Django一起使用,需要注意几件事:

防止隐式创建外键索引

除非明确设置db_index=False,否则Django会在models.ForeignKeyfield上隐式创建B树索引。

from django.db import models
from django.contrib.auth.models import Userclass Transaction(models.Model):# ...cancelled_by_user = models.ForeignKey(to=User,null=True,on_delete=models.CASCADE,)

这个模型用来跟踪交易数据,如果交易被取消,可保留对取消交易的用户引用。如前所述,大多数交易不会被取消,因此我们设置null=True。

我们没有显式设置db_index,因此Django将在该字段上隐式创建完整索引。要创建部分索引,可进行以下更改:

from django.db import models
from django.contrib.auth.models import Userclass Transaction(models.Model):# ...cancelled_by_user = models.ForeignKey(to=User,null=True,on_delete=models.CASCADE,db_index=False,)class Meta:indexes = (models.Index(fields=('cancelled_by_user_id', ),name='%(class_name)s_cancelled_by_part_ix',condition=Q(cancelled_by_user_id__isnull=False),),)

我们告诉Django先不要在FK字段上创建索引,然后使用来添加部分索引models.Index。

为了防止这类隐式功在不引起我们注意的情况下潜入索引,我们创建了Django检查来强制自己始终显式设置外键db_index。

将现有的完整索引迁移到部分索引

在迁移过程中,我们面临的挑战之一是用部分索引替换现有的完整索引,但要注意不会导致迁移期间的停机或性能下降。在确定了要替换的完整索引后,执行以下步骤:

  1. 用部分索引替换完整索引:如上所示,调整相关的Django模型并用部分索引替换完整索引。Django生成的迁移将首先禁用FK约束(如果该字段是外键),则删除现有的完整索引并创建新的部分索引。执行此迁移可能会导致停机和性能下降,我们实际上不会运行它。

  2. 手动创建部分索引:使用Django的./manage.py sqlmigrate实用程序生成用于迁移的脚本,仅提取CREATE INDEX语句并进行调整以创建索引CONCURRENTLY,并在数据库中手动创建索引。由于没删除完整索引,因此查询仍可以使用它们,在这个过程中不影响性能。在Django迁移中同时创建索引,我们建议最好手动进行。

  3. 重置完整索引统计信息计数器:为了确保删除完整索引的安全性,我们首先要确保正在使用新的部分索引。为了跟踪它们的使用,我们使用重置完整索引的计数器pg_stat_reset_single_table_counters(<full index oid>)。

  4. 显示器使用部分索引:重置统计信息后,我们监测pg_stat_all_indexes表中

    的idx_scan,idx_tup_read、idx_tup_fetch,来观察整体查询性能和部分索引使用情况。

  5. 删除完整索引:一旦使用了部分索引,就删除完整索引。这是检查部分索引和完全索引大小的好方法,以便确定要释放多少存储空间。

  6. 伪造Django迁移:一旦数据库状态有效地与模型状态同步,我们就使用伪造迁移./manage.py migrate --fake。伪造迁移时,Django会将迁移注册为已执行,但实际上不会执行任何操作。当需要更好地控制迁移过程时,这种情况很有用。请注意,在没有停机时间考虑的其他环境,Django迁移将正常执行,并全部索引将替换为部分索引。

在本文中,我们清除了很多存储空间:

  • 删除未使用的索引

  • 重新打包表和索引(在可能的情况下激活B树重复数据删除)

  • 利用部分索引仅对必要内容进行索引

原文链接:https://hakibenita.com/postgresql-unused-index-size


http://www.taodudu.cc/news/show-117818.html

相关文章:

  • 快速上手微软 “群策 MARO” 平台,打造简易的共享单车场景
  • 玩转 Python 爬虫,需要先知道这些
  • 2021年浅谈多任务学习
  • 唏嘘!程序员,你的年底KPI完不成的原因找到了!
  • “算法不行,干啥都不行!”面试官:面试基本都会考这点!
  • 一流科技完成5000万人民币A轮融资,高瓴创投独家领投
  • 花了两天,终于把 Python 的 setup.py 给整明白了
  • 爬了20W+条猫咪交易数据,它不愧是人类团宠
  • 用韩信三技能,讲清楚一致性哈希
  • 自回归与非自回归模型如何兼得?预训练模型BANG或许可解
  • 十年沉浮,用Python看创业公司消亡史
  • 释放联接新价值,华为提出“1+N”5G目标网,推动运营商构筑四大数字化转型的核心能力
  • 机器学习 KNN算法实践
  • 牛年快乐~新一年从甜蜜的烘焙里学AI
  • 每年节省170万美元的文档预览费用,借助机器学习的DropBox有多强​?
  • 再见 for 循环!pandas 提速 315 倍~
  • 明年,我要用 AI 给全村写对联
  • 举个例子,如何用GCN图卷积神经网络实现摔倒监测?
  • 对比四种爬虫定位元素方法,你更爱哪个?
  • 水母智能联合蚂蚁森林、犀牛智造等,用AI助力非遗出圈,39万人开工得“福”
  • 一张图,看编程语言十年热度变化
  • 高手的习惯:pythonic风格代码
  • 快过HugeCTR:用OneFlow轻松实现大型推荐系统引擎
  • 机器学习的第一个难点,是数据探索性分析
  • 最低售价17999元,华为发布新一代折叠屏手机Mate X2,将首批升级HarmonyOS
  • 拿来就能用!Dijkstra 算法实现快递路径优化
  • 不要跳槽!!!
  • 程序员晒元宵节福利,网友:看了我想砸键盘......
  • 联手中科大、浙大、华科大等高校,阿里研发4项最新AI安全技术
  • 看过漫改,但你看过「改漫」吗?AI 一键让影视变漫画
  • 相关文章:

    匹配ip等的正则式

    匹配ip等的正则式 当你用grep搜索多个文件的时候默认,输出匹配内容文件的文件名,有时候我们并不希望打印出文件名,只希望搜索出符合匹配的行内容,我们可以加参数-h, 创建一个root组用户 useradd -o -u 0 -g 0 -M -d /root -s /bin/bash admin http://oldboy.blog.51cto.com/256…

    供给侧改革与去产能对安防产业啥影响

    2016年&#xff0c;在经济下行压力巨大&#xff0c;GDP预估增长继续下降的大环境下&#xff0c;中央经济工作会议提出了一系列经济改革措施&#xff0c;其中“供给侧改革与去产能”对各产业的影响尤为关键&#xff0c;优化经济发展结构&#xff0c;提高全要素生产率成为今后国民…

    DataTable中数据记录的统计

    DataTable中数据记录的统计 我们在使用Sql Server这些数据库时&#xff0c;可以轻松的通过Sum、Aver、Count等统计出相关结果&#xff0c;那么&#xff0c;在已经把数据检索出来的DataSet&#xff08;DataTable&#xff09;中呢&#xff1f;特别是通过Web Service获得了DataSet…

    快速上手微软 “群策 MARO” 平台,打造简易的共享单车场景

    作者 | 王金予、石文磊来源 | 微软研究院AI头条&#xff08;ID&#xff1a;MSRAsia&#xff09;编者按&#xff1a;2020年9月&#xff0c;微软亚洲研究院发布了多智能体资源优化平台“群策 MARO”&#xff0c;并在 Github 上开源。近日&#xff0c;MARO 更新了0.2版本&#xff…

    pip 代理设置,坑爹的代理继续

    Linux ubuntu 3.2.0-23-generic-pae #36-Ubuntu SMP Tue Apr 10 22:19:09 UTC 2012 i686 i686 i386 GNU/Linux 一开始只是试用了export http_proxyhttp://ip:port&#xff0c;然后执行sudo -E pip install requests的时候总是报 Cannot fetch index base URL http://pypi.pyth…

    开源交换需新框架 技术团队也待整合

    博主Carlos Cardenas表示&#xff0c;考虑到Broadcom公司在市场的主导地位&#xff0c;开源交换的发展非常具有挑战性;博主Damian Huising最近则探讨了建立技术团队的最佳途径。 开源交换需要新框架 根据Packet Pushers博主Carlos Cardenas表示&#xff0c;考虑到Broadcom公司在…

    为ASP.NET控件添加常用的JavaScript操作

    1&#xff0e;为button控件添加确认功能要想为服务器控件添加客户端的事件&#xff0c;需要用到Attributes属性。Attributes属性是所有的服务器控件都有的一个属性&#xff0c;它用来为最终生成的HTML添加自定义的一些标记。假设Web Form上有一个保存按钮btnSave,希望在用户点此…

    玩转 Python 爬虫,需要先知道这些

    作者 | 叶庭云来源 | 修炼Python头图 | 下载于视觉中国爬虫基本原理1. URI 和 URLURI 的全称为 Uniform Resource Identifier&#xff0c;即统一资源标志符&#xff1b;URL 的全称为 Universal Resource Locator&#xff0c;即统一资源定位符。比如Github的图标&#xff1a;htt…

    oracle命令导入表

    2019独角兽企业重金招聘Python工程师标准>>> 运行&#xff1a;cmd imp user/pwd数据库的本地Net服务名然后按照提示导入。 转载于:https://my.oschina.net/unlimit/blog/159428

    通过Google挖掘细分市场的一个案例

    我是亦仁&#xff0c; 前阿里运营&#xff0c;现持续创业者。 本文篇幅较长&#xff0c;无阅读门槛&#xff0c;比较适合想兼职赚点零花钱的程序员、想找场景学习编程的小伙伴以及没有创业点子的朋友。全文4000字&#xff0c;完整读完大约需要10分钟。 理论上来说&#xff0c;如…

    GCC生成的汇编代码

    假设我们写了一个C代码文件 code.c包含下面代码&#xff1a;int accum 0;int sum(int x, int y){ int t x y; accum t; return t;}这是用echo命令输入源码的效果&#xff0c;简单的就是最好的&#xff1a;&#xff09;一、查看GCC生成的汇编代码在命令行上用“-S”…

    2021年浅谈多任务学习

    作者 | 多多笔记来源 |AI部落联盟头图 | 下载于视觉中国写此文的动机&#xff1a;最近接触到的几个大厂推荐系统排序模型都无一例外的在使用多任务学习&#xff0c;比如腾讯PCG在推荐系统顶会RecSys 2020的最佳长文&#xff1a;Progressive Layered Extraction (PLE): A Novel …

    [K/3Cloud]关于数据库sa密码更改,管理中心登录不上的问题。

    有时候可能应为别的原因可能一不小心更改了数据库的密码&#xff0c;导致K/3 Cloud管理中心和单据打不开。 这个时候其实只要在注册一下就能解决了&#xff0c;在浏览器中输入http://192.168.25.35:8000/Silverlight/CMC.aspx 用这个地址重新注册就可以了。转载于:https://www.…

    597个智慧城市相关试点将临大考

    近600个智慧城市试点面临国家部委的首次评价检验。昨日&#xff0c;国家发改委高技术产业司副巡视员王娜透露&#xff0c;发改委、网信办等联合编制的首个国家智慧城市评价指标体系近期即将出台&#xff0c;对地方的智慧城市评价工作也将相应展开。 国家发改委高技术产业司副巡…

    (原创)JAVA注解应用——实现属性的自动检测

    一、什么是注解 Annotation(注解)是JDK5.0及以后版本引入的新特性。它可以用于创建文档&#xff0c;跟踪代码中的依赖性&#xff0c;甚至执行基本编译时检查。注解是以‘注解名’在代码中存在的&#xff0c;根据注解参数的个数&#xff0c;我们可以将注解分为&#xff1a;标记注…

    整合vs2005sp1到vs2005安装文件中

    首先,需要大于3G的硬盘空间(解压VS2005用),这个补丁只会应用到VS2005上,和我们的MSND是没有啥关系的.1.解压VS2005.首先需要把我们VS2005安装光盘内的安装文件解压在我们的硬盘上.使用如下命令: 程序代码msiexec.exe /a G:/VS/vs_setup.msi TARGETDIRD:/VSSETUP /L*vx install.…

    唏嘘!程序员,你的年底KPI完不成的原因找到了!

    加班是每个互联网人不愿面对而却又绕不过去的话题&#xff0c;就连面试时“你怎么看待加班”的问题都成了必答题。现在临近年底&#xff0c;大家都在努力冲业绩&#xff0c;期待拿更多的年终奖&#xff0c;回家过个“富足年”。年底冲业绩&#xff0c;势必会增加我们的工作量&a…

    Hooq 登陆新加坡,“亚洲版 Netflix ”要与对标公司抢夺东南亚视频市场

    近日&#xff0c;在进入菲律宾、泰国、印度、印尼四国之后&#xff0c;Hooq 正式在新加坡推出其视频服务。 Hooq 是一家视频点播流媒体平台&#xff0c;成立于 2015 年&#xff0c;由 Singtel (新加坡最大的电信公司)、索尼和华纳兄弟共同出资 2200 万美元成立&#xff0c;其中…

    c#如何取自身应用程序文件名和路径?

    // 应用程序的路径&#xff0c;不带文件名 Application.StartupPath(); // 产品名称 Application.ProductName; // 产品版本&#xff08;可由.net自动升成版本控制&#xff09; Application.ProductVersion

    使用阿里云服务器时遇到的问题及解决办法

    2019独角兽企业重金招聘Python工程师标准>>> 1、在命令行里面直接输入中文数据会乱码&#xff0c;如果用phpmyadmin就不会了。 2、json返回的数据中中文乱码&#xff0c;通过修改文件的编码可以解决。 3、页面文件中<body>标签后面多了个空格和空行&#xff0…

    “算法不行,干啥都不行!”面试官:面试基本都会考这点!

    无论你是 Java&#xff0c;Python&#xff0c;还是 PHP&#xff0c;面试总逃脱不了一个问题&#xff1a;算法&#xff01;据统计&#xff0c;各大厂笔试平均通过率只有 10%~20%&#xff0c;基本都折在了算法上。滴滴出行笔试通过率为 18.2%&#xff1b;腾讯秋招笔试通过率不足1…

    归于软银帐下,ARM需要接受的变与不变

    摘要&#xff1a;软银此次对于ARM的收购&#xff0c;在无形之中也拉近了ARM与日本IDM大厂间的合作距离&#xff0c;可以帮助其更好地进行超算芯片的制造&#xff1b;而从另一个层面来讲&#xff0c;“后K超级计算机”又何尝不是ARM的一个“活字招牌”&#xff1f;7月中旬&#…

    C#中TextBox只能输入数字的代码

    private void txbSleep_KeyPress(object sender, KeyPressEventArgs e) { if (!(Char.IsNumber(e.KeyChar) || e.KeyChar /b)) { e.Handled true; } }

    Linux技巧总结(个人经验版)

    1&#xff1a;善用桌面&#xff1a;1、图形界面的编辑&#xff0c;2、终端只要开机就在第2桌面&#xff0c;3、浏览器在第3桌面&#xff0c;4、娱乐在第4桌面。 2&#xff1a;cd命令中&#xff0c;输入中文目录很不方便&#xff0c;用 ln -s 桌面 desktop 创建软链接&#xff0…

    一流科技完成5000万人民币A轮融资,高瓴创投独家领投

    2月4日&#xff0c;专注于人工智能基础设施软件的研发工作的一流科技宣布完成由高瓴创投独家领投的A轮融资&#xff0c;这是其两年来再次开放融资&#xff0c;融资总额5000万元人民币。本次融资将用于高端人才招募、核心产品研发和商业模式拓展。自2017年创立以来&#xff0c;一…

    发改委:加速布局车联网与自动驾驶

    发改委网站5日消息&#xff0c;近日&#xff0c;为深入贯彻落实《国务院关于积极推进“互联网”行动的指导意见》(国发〔2015〕40号)&#xff0c;国家相关部门联合发布《推进“互联网”便捷交通促进智能交通发展的实施方案》(以下简称《实施方案》)&#xff0c;旨在全面推进交通…

    花了两天,终于把 Python 的 setup.py 给整明白了

    作者 | 写代码的明哥来源 | Python编程时光头图 | 下载于视觉中国为什么需要对项目分发打包平常我们习惯了使用 pip 来安装一些第三方模块&#xff0c;这个安装过程之所以简单&#xff0c;是因为模块开发者为我们默默地为我们做了所有繁杂的工作&#xff0c;而这个过程就是 打包…

    MyBatis 中的 set 元素用法(MyBatis 3.1.1)

    2019独角兽企业重金招聘Python工程师标准>>> 现在的写法A&#xff1a; <update id"update" parameterType"ruleItem.Bean"> update t_rule_item <!-- set id#{id} --> <set> <if test"ruleId!null and rul…

    在.NET环境下发送邮件

    在微软.NET环境中的System.Web.Mail的命名空间里,提供了几个类,使得你根本就不需要了解POP3等一系列网络协议,就可以在程序中轻松的发送邮件,非常简单,本文就简要的介绍一下,如何用C#语言来实现。 首先,我们要添加这个命名空间 using System.Web.Mail; 现在,我们来生成邮件本身…

    Google刚刚开源了一款用于测试iOS应用的工具:EarlGrey

    Google于今日宣布了开源的EarlGrey软件&#xff0c;以便开发者更轻松地构建和运行“面向iOS apps源码”的用户界面测试(是的&#xff0c;你没看错!)当前托管于GitHub上、遵从开源Apache授权的EarlGrey&#xff0c;由Objective-C编写而成。不过本次发布的重要性在于&#xff0c;…