neo4j cypher_Neo4j:Cypher –避免热切

neo4j cypher

当心渴望的管道

当心渴望的管道


尽管我喜欢Cypher的LOAD CSV命令使它容易地将数据获取到Neo4j中的方法,但它目前打破了最不惊奇的规则,因为它急切地在所有行中加载某些查询,即使是那些使用定期提交的查询。

这是我的同事Michael在他的第二篇博客文章中指出的,它解释了如何成功使用LOAD CSV :

即使遵循我之前的建议,人们遇到的最大问题是,对于超过一百万行的大量导入,Cypher遇到了内存不足的情况。

与提交大小无关 ,因此即使是小批量的PERIODIC COMMIT也会发生。

最近,我花了几天时间在具有4GB RAM的Windows机器上将数据导入Neo4j,所以我比Michael建议的更早看到了这个问题。

Michael解释了如何确定您的查询是否遭受意外的急切评估:

如果分析该查询,则会看到查询计划中有一个“急切”步骤。

那就是“拉入所有数据”的地方。

您可以通过在单词“ PROFILE”前面加上前缀来配置查询。 您需要在Web浏览器的/ webadmin控制台中或使用Neo4j shell运行查询。

我为查询执行了此操作,并且能够识别得到快速评估的查询模式,在某些情况下,我们可以解决该问题。

我们将使用Northwind数据集来演示Eager管道如何潜入我们的查询中,但请记住,该数据集足够小,不会引起问题。

这是文件中的行的样子:

$ head -n 2 data/customerDb.csv
OrderID,CustomerID,EmployeeID,OrderDate,RequiredDate,ShippedDate,ShipVia,Freight,ShipName,ShipAddress,ShipCity,ShipRegion,ShipPostalCode,ShipCountry,CustomerID,CustomerCompanyName,ContactName,ContactTitle,Address,City,Region,PostalCode,Country,Phone,Fax,EmployeeID,LastName,FirstName,Title,TitleOfCourtesy,BirthDate,HireDate,Address,City,Region,PostalCode,Country,HomePhone,Extension,Photo,Notes,ReportsTo,PhotoPath,OrderID,ProductID,UnitPrice,Quantity,Discount,ProductID,ProductName,SupplierID,CategoryID,QuantityPerUnit,UnitPrice,UnitsInStock,UnitsOnOrder,ReorderLevel,Discontinued,SupplierID,SupplierCompanyName,ContactName,ContactTitle,Address,City,Region,PostalCode,Country,Phone,Fax,HomePage,CategoryID,CategoryName,Description,Picture
10248,VINET,5,1996-07-04,1996-08-01,1996-07-16,3,32.38,Vins et alcools Chevalier,59 rue de l'Abbaye,Reims,,51100,France,VINET,Vins et alcools Chevalier,Paul Henriot,Accounting Manager,59 rue de l'Abbaye,Reims,,51100,France,26.47.15.10,26.47.15.11,5,Buchanan,Steven,Sales Manager,Mr.,1955-03-04,1993-10-17,14 Garrett Hill,London,,SW1 8JR,UK,(71) 555-4848,3453,\x,"Steven Buchanan graduated from St. Andrews University, Scotland, with a BSC degree in 1976.  Upon joining the company as a sales representative in 1992, he spent 6 months in an orientation program at the Seattle office and then returned to his permanent post in London.  He was promoted to sales manager in March 1993.  Mr. Buchanan has completed the courses ""Successful Telemarketing"" and ""International Sales Management.""  He is fluent in French.",2,http://accweb/emmployees/buchanan.bmp,10248,11,14,12,0,11,Queso Cabrales,5,4,1 kg pkg.,21,22,30,30,0,5,Cooperativa de Quesos 'Las Cabras',Antonio del Valle Saavedra,Export Administrator,Calle del Rosal 4,Oviedo,Asturias,33007,Spain,(98) 598 76 54,,,4,Dairy Products,Cheeses,\x

合并,合并,合并

我们要做的第一件事是为每个员工和每个订单创建一个节点,然后在它们之间创建一个关系。

我们可以从以下查询开始:

USING PERIODIC COMMIT 1000
LOAD CSV WITH HEADERS FROM "file:/Users/markneedham/projects/neo4j-northwind/data/customerDb.csv" AS row
MERGE (employee:Employee {employeeId: row.EmployeeID})
MERGE (order:Order {orderId: row.OrderID})
MERGE (employee)-[:SOLD]->(order)

这样就可以了,但是如果我们像这样对查询进行概要分析……

PROFILE LOAD CSV WITH HEADERS FROM "file:/Users/markneedham/projects/neo4j-northwind/data/customerDb.csv" AS row
WITH row LIMIT 0
MERGE (employee:Employee {employeeId: row.EmployeeID})
MERGE (order:Order {orderId: row.OrderID})
MERGE (employee)-[:SOLD]->(order)

…我们会在第三行看到“渴望”:

==> +----------------+------+--------+----------------------------------+-----------------------------------------+
==> |       Operator | Rows | DbHits |                      Identifiers |                                   Other |
==> +----------------+------+--------+----------------------------------+-----------------------------------------+
==> |    EmptyResult |    0 |      0 |                                  |                                         |
==> | UpdateGraph(0) |    0 |      0 |    employee, order,   UNNAMED216 |                            MergePattern |
==> |          Eager |    0 |      0 |                                  |                                         |
==> | UpdateGraph(1) |    0 |      0 | employee, employee, order, order | MergeNode; :Employee; MergeNode; :Order |
==> |          Slice |    0 |      0 |                                  |                            {  AUTOINT0} |
==> |        LoadCSV |    1 |      0 |                              row |                                         |
==> +----------------+------+--------+----------------------------------+-----------------------------------------+

您会注意到,当我们分析每个查询时,我们将删除定期提交部分,并添加“ WITH row LIMIT 0”。 这使我们能够生成足够的查询计划来标识“急切”运算符,而无需实际导入任何数据。

我们希望将该查询分为两个查询,以便可以不急于处理它:

USING PERIODIC COMMIT 1000
LOAD CSV WITH HEADERS FROM "file:/Users/markneedham/projects/neo4j-northwind/data/customerDb.csv" AS row
WITH row LIMIT 0
MERGE (employee:Employee {employeeId: row.EmployeeID})
MERGE (order:Order {orderId: row.OrderID})
==> +-------------+------+--------+----------------------------------+-----------------------------------------+
==> |    Operator | Rows | DbHits |                      Identifiers |                                   Other |
==> +-------------+------+--------+----------------------------------+-----------------------------------------+
==> | EmptyResult |    0 |      0 |                                  |                                         |
==> | UpdateGraph |    0 |      0 | employee, employee, order, order | MergeNode; :Employee; MergeNode; :Order |
==> |       Slice |    0 |      0 |                                  |                            {  AUTOINT0} |
==> |     LoadCSV |    1 |      0 |                              row |                                         |
==> +-------------+------+--------+----------------------------------+-----------------------------------------+

现在我们已经创建了员工和订单,我们可以将他们加入在一起:

USING PERIODIC COMMIT 1000
LOAD CSV WITH HEADERS FROM "file:/Users/markneedham/projects/neo4j-northwind/data/customerDb.csv" AS row
MATCH (employee:Employee {employeeId: row.EmployeeID})
MATCH (order:Order {orderId: row.OrderID})
MERGE (employee)-[:SOLD]->(order)
==> +----------------+------+--------+-------------------------------+-----------------------------------------------------------+
==> |       Operator | Rows | DbHits |                   Identifiers |                                                     Other |
==> +----------------+------+--------+-------------------------------+-----------------------------------------------------------+
==> |    EmptyResult |    0 |      0 |                               |                                                           |
==> |    UpdateGraph |    0 |      0 | employee, order,   UNNAMED216 |                                              MergePattern |
==> |      Filter(0) |    0 |      0 |                               |          Property(order,orderId) == Property(row,OrderID) |
==> | NodeByLabel(0) |    0 |      0 |                  order, order |                                                    :Order |
==> |      Filter(1) |    0 |      0 |                               | Property(employee,employeeId) == Property(row,EmployeeID) |
==> | NodeByLabel(1) |    0 |      0 |            employee, employee |                                                 :Employee |
==> |          Slice |    0 |      0 |                               |                                              {  AUTOINT0} |
==> |        LoadCSV |    1 |      0 |                           row |                                                           |
==> +----------------+------+--------+-------------------------------+-----------------------------------------------------------+

眼中没有渴望!

比赛,比赛,比赛,合并,合并

如果我们快进几步,我们现在可能已经将导入脚本重构到了我们在一个查询中创建节点并在另一个查询中创建关系的地步。

我们的create查询按预期工作:

USING PERIODIC COMMIT 1000
LOAD CSV WITH HEADERS FROM "file:/Users/markneedham/projects/neo4j-northwind/data/customerDb.csv" AS row
MERGE (employee:Employee {employeeId: row.EmployeeID})
MERGE (order:Order {orderId: row.OrderID})
MERGE (product:Product {productId: row.ProductID})
==> +-------------+------+--------+----------------------------------------------------+--------------------------------------------------------------+
==> |    Operator | Rows | DbHits |                                        Identifiers |                                                        Other |
==> +-------------+------+--------+----------------------------------------------------+--------------------------------------------------------------+
==> | EmptyResult |    0 |      0 |                                                    |                                                              |
==> | UpdateGraph |    0 |      0 | employee, employee, order, order, product, product | MergeNode; :Employee; MergeNode; :Order; MergeNode; :Product |
==> |       Slice |    0 |      0 |                                                    |                                                 {  AUTOINT0} |
==> |     LoadCSV |    1 |      0 |                                                row |                                                              |
==> +-------------+------+--------+----------------------------------------------------+------------------------------------------------------------

现在,我们在图表中有了员工,产品和订单。 现在让我们在三者之间建立关系:

USING PERIODIC COMMIT 1000
LOAD CSV WITH HEADERS FROM "file:/Users/markneedham/projects/neo4j-northwind/data/customerDb.csv" AS row
MATCH (employee:Employee {employeeId: row.EmployeeID})
MATCH (order:Order {orderId: row.OrderID})
MATCH (product:Product {productId: row.ProductID})
MERGE (employee)-[:SOLD]->(order)
MERGE (order)-[:PRODUCT]->(product)

如果我们描述,我们会发现Eager再次潜入了!

==> +----------------+------+--------+-------------------------------+-----------------------------------------------------------+
==> |       Operator | Rows | DbHits |                   Identifiers |                                                     Other |
==> +----------------+------+--------+-------------------------------+-----------------------------------------------------------+
==> |    EmptyResult |    0 |      0 |                               |                                                           |
==> | UpdateGraph(0) |    0 |      0 |  order, product,   UNNAMED318 |                                              MergePattern |
==> |          Eager |    0 |      0 |                               |                                                           |
==> | UpdateGraph(1) |    0 |      0 | employee, order,   UNNAMED287 |                                              MergePattern |
==> |      Filter(0) |    0 |      0 |                               |    Property(product,productId) == Property(row,ProductID) |
==> | NodeByLabel(0) |    0 |      0 |              product, product |                                                  :Product |
==> |      Filter(1) |    0 |      0 |                               |          Property(order,orderId) == Property(row,OrderID) |
==> | NodeByLabel(1) |    0 |      0 |                  order, order |                                                    :Order |
==> |      Filter(2) |    0 |      0 |                               | Property(employee,employeeId) == Property(row,EmployeeID) |
==> | NodeByLabel(2) |    0 |      0 |            employee, employee |                                                 :Employee |
==> |          Slice |    0 |      0 |                               |                                              {  AUTOINT0} |
==> |        LoadCSV |    1 |      0 |                           row |                                                           |
==> +----------------+------+--------+-------------------------------+-----------------------------------------------------------+

在这种情况下,Eager发生在我们第二次致电MERGE时,正如Michael在他的帖子中指出的:

问题是,在单个Cypher语句中,您必须隔离会进一步影响匹配的更改,例如,当您创建带有标签的节点时,该标签突然被以后的MATCH或MERGE操作所匹配。

在这种情况下,我们可以通过使用单独的查询来创建关系来解决该问题:

LOAD CSV WITH HEADERS FROM "file:/Users/markneedham/projects/neo4j-northwind/data/customerDb.csv" AS row
MATCH (employee:Employee {employeeId: row.EmployeeID})
MATCH (order:Order {orderId: row.OrderID})
MERGE (employee)-[:SOLD]->(order)
==> +----------------+------+--------+-------------------------------+-----------------------------------------------------------+
==> |       Operator | Rows | DbHits |                   Identifiers |                                                     Other |
==> +----------------+------+--------+-------------------------------+-----------------------------------------------------------+
==> |    EmptyResult |    0 |      0 |                               |                                                           |
==> |    UpdateGraph |    0 |      0 | employee, order,   UNNAMED236 |                                              MergePattern |
==> |      Filter(0) |    0 |      0 |                               |          Property(order,orderId) == Property(row,OrderID) |
==> | NodeByLabel(0) |    0 |      0 |                  order, order |                                                    :Order |
==> |      Filter(1) |    0 |      0 |                               | Property(employee,employeeId) == Property(row,EmployeeID) |
==> | NodeByLabel(1) |    0 |      0 |            employee, employee |                                                 :Employee |
==> |          Slice |    0 |      0 |                               |                                              {  AUTOINT0} |
==> |        LoadCSV |    1 |      0 |                           row |                                                           |
==> +----------------+------+--------+-------------------------------+-----------------------------------------------------------+
USING PERIODIC COMMIT 1000
LOAD CSV WITH HEADERS FROM "file:/Users/markneedham/projects/neo4j-northwind/data/customerDb.csv" AS row
MATCH (order:Order {orderId: row.OrderID})
MATCH (product:Product {productId: row.ProductID})
MERGE (order)-[:PRODUCT]->(product)
==> +----------------+------+--------+------------------------------+--------------------------------------------------------+
==> |       Operator | Rows | DbHits |                  Identifiers |                                                  Other |
==> +----------------+------+--------+------------------------------+--------------------------------------------------------+
==> |    EmptyResult |    0 |      0 |                              |                                                        |
==> |    UpdateGraph |    0 |      0 | order, product,   UNNAMED229 |                                           MergePattern |
==> |      Filter(0) |    0 |      0 |                              | Property(product,productId) == Property(row,ProductID) |
==> | NodeByLabel(0) |    0 |      0 |             product, product |                                               :Product |
==> |      Filter(1) |    0 |      0 |                              |       Property(order,orderId) == Property(row,OrderID) |
==> | NodeByLabel(1) |    0 |      0 |                 order, order |                                                 :Order |
==> |          Slice |    0 |      0 |                              |                                           {  AUTOINT0} |
==> |        LoadCSV |    1 |      0 |                          row |                                                        |
==> +----------------+------+--------+------------------------------+--------------------------------------------------------+

合并,设置

我尝试使LOAD CSV脚本尽可能地幂等,这样,如果我们将更多行或更多列的数据添加到CSV中,我们可以重新运行查询而不必重新创建所有内容。

这可以引导您进入以下创建供应商的模式:

USING PERIODIC COMMIT 1000
LOAD CSV WITH HEADERS FROM "file:/Users/markneedham/projects/neo4j-northwind/data/customerDb.csv" AS row
MERGE (supplier:Supplier {supplierId: row.SupplierID})
SET supplier.companyName = row.SupplierCompanyName

我们要确保只有一个具有该SupplierID的Supplier,但是我们可能会逐步添加新属性,并决定使用'SET'命令替换所有内容。 如果我们分析该查询,则“渴望”会潜伏:

==> +----------------+------+--------+--------------------+----------------------+
==> |       Operator | Rows | DbHits |        Identifiers |                Other |
==> +----------------+------+--------+--------------------+----------------------+
==> |    EmptyResult |    0 |      0 |                    |                      |
==> | UpdateGraph(0) |    0 |      0 |                    |          PropertySet |
==> |          Eager |    0 |      0 |                    |                      |
==> | UpdateGraph(1) |    0 |      0 | supplier, supplier | MergeNode; :Supplier |
==> |          Slice |    0 |      0 |                    |         {  AUTOINT0} |
==> |        LoadCSV |    1 |      0 |                row |                      |
==> +----------------+------+--------+--------------------+----------------------+

我们可以使用“ ON CREATE SET”和“ ON MATCH SET”以一些重复的代价来解决此问题:

USING PERIODIC COMMIT 1000
LOAD CSV WITH HEADERS FROM "file:/Users/markneedham/projects/neo4j-northwind/data/customerDb.csv" AS row
MERGE (supplier:Supplier {supplierId: row.SupplierID})
ON CREATE SET supplier.companyName = row.SupplierCompanyName
ON MATCH SET supplier.companyName = row.SupplierCompanyName
==> +-------------+------+--------+--------------------+----------------------+
==> |    Operator | Rows | DbHits |        Identifiers |                Other |
==> +-------------+------+--------+--------------------+----------------------+
==> | EmptyResult |    0 |      0 |                    |                      |
==> | UpdateGraph |    0 |      0 | supplier, supplier | MergeNode; :Supplier |
==> |       Slice |    0 |      0 |                    |         {  AUTOINT0} |
==> |     LoadCSV |    1 |      0 |                row |                      |
==> +-------------+------+--------+--------------------+----------------------+

使用我一直在使用的数据集,在某些情况下可以避免OutOfMemory异常,而在其他情况下,可以将运行查询所花费的时间减少3倍。

随着时间的流逝,我希望所有这些情况都将得到解决,但是从Neo4j 2.1.5开始,这些是我已经确定过急的模式。

如果您知道其他任何人,请告诉我,我可以将其添加到帖子中或撰写第二部分。

翻译自: https://www.javacodegeeks.com/2014/10/neo4j-cypher-avoiding-the-eager.html

neo4j cypher

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/339351.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++实现简单走迷宫的代码

用n*n个小方格代表迷宫,每个方格上有一个字符0或1,0代表这个格子不能走,1代表这个格子可以走。只能一个格子一个走,而且只能从一个格子向它的上、下、左、右四个方向走,且不能重复。迷宫的入口和出口分别位于左上角和右…

利用C/C++实现较完整贪吃蛇游戏

利用空余时间写出了这么一个简单的小游戏,直接使用dos界面运行。那么问题来了,如何让一个字符在dos界面上自由移动???对于这个问题我采用的解决方案是实现gotoxy函数来控制指针位置从而实现字符的移动。那么我们就先来…

C++中的函数汇总(新手必知)!

math.h 数学函数库,一些数学计算的公式的具体实现是放在math.h里,具体有:1 三角函数double sin (double); double cos (double); double tan (double);2 反三角函数double asin (double); 结果介于[-PI/2, PI/2] double acos (double); 结果介于[0, PI] double …

艾伦图灵_Java英雄:丹·艾伦

艾伦图灵“ Java英雄 ”系列休息了很长时间。 老实说,我想即使有很多人我想把它包括在这里,它也可能会在茫茫荒野中终结。 丹是其中之一。 我第一次要求他捐款已经差不多一年半了,并且在此期间发生的所有事情使我安然无not。 但是以下内容在J…

26条C++的经典语录,哪几句戳中你的心!

2019年悄悄的已经过了三分之二,C你了解了多少?随着互联网的发展,c作为底层语言的龙头老大,是时候站出来了!如何学好C,老夫我利用平生所学,整理出26条C经典语录,希望能帮助到每一个热爱C的同学&a…

C语言的10大基础算法

算法是一个程序和软件的灵魂,作为一名优秀的程序员,只有对一些基础的算法有着全面的掌握,才会在设计程序和编写代码的过程中显得得心应手。本文是近百个C语言算法系列的第二篇,包括了经典的Fibonacci数列、简易计算器、回文检查、…

C++实现简单的信息管理系统

本文为大家分享C实现简单的信息管理系统&#xff0c;小编之前在学习的时候也要做一些管理系统&#xff0c;在网上查了许多资料&#xff0c;现在我把资料分享给大家&#xff0c;希望能够帮助到大家。#include <stdio.h> #include <stdlib.h> #include "file.…

C# 面向对象三大特性:封装、继承、多态

面向对象有封装、继承、多态这三个特性&#xff0c;面向对象编程按照现实世界的特点来管理复杂的事物&#xff0c;把它们抽象为对象&#xff0c;具有自己的状态和行为&#xff0c;通过对消息的反应来完成任务。这种编程方法提供了非常强大的多样性&#xff0c;大大增加了代码的…

行车记录仪设置php,行车记录仪怎么调设置

行车记录仪设置方法如下&#xff1b;1、视频分辨率视频分辨率一直是厂家着力宣传的卖点&#xff0c;从最初的高清720P、全高清1080P到现在的超高清2K&#xff0c;车主朋友们也都耳熟能详。一般行车记录仪的分辨率提供以下几个选项&#xff1a;1080FHD、720P、WVGA、VGA。视频分…

C++面试常见问题整理汇总(面试者必看哦!)

1. 继承方式public   父类的访问级别不变#include <iostream> using namespace std; class base { public: void printa() { cout <<"base"<< endl; } protected: void printhello() { cout <<"helo"<< endl; } p…

C++ vector使用的一些注意事项

更多精彩&#xff0c;请点击上方蓝字关注我们&#xff01;1. 初始化c 11以后新增了大括号{}的初始化方式&#xff0c;需要注意与()的区别,如&#xff1a;std::vector<int> vecTest1(5); //初始化5个元素&#xff0c;每个都是0std::vector<int> vecTest2{ 5…

最全的C++面试题来啦!(来自各大一线互联网)

更多精彩&#xff0c;请点击上方蓝字关注我们&#xff01;此面试题全部由成功就业学员提供&#xff0c;来自各大一线互联网企业&#xff0c;在此谢谢他们的贡献&#xff01;1.new、delete、malloc、free关系delete会调用对象的析构函数,和new对应free只会释放内存&#xff0c;n…

基于C++实现五子棋AI算法思想

更多精彩&#xff0c;请点击上方蓝字关注我们&#xff01;今天我想要分享一下我做五子棋AI的思路。因为在做这个之前&#xff0c;我没有接触过任何像这种类似的东西。通过这一次&#xff0c;我也算是有所了解&#xff0c;我的思路也是来自很多网络上的博客&#xff0c;看了很多…

java代码初体验_第一次Java 8体验

java代码初体验像世界其他地方一样&#xff0c;我深深地爱上了Slack。 为什么&#xff1f; 原因很多&#xff0c;但主要的原因是它提供了一种围绕通讯而非工具真正构建SDLC流程的新方法。 您认为这些天哪个更常见&#xff0c;杂乱无章的机智团队在荒野中四处徘徊&#xff0c;尽…

C++学习 | 面试官:我们只想要这样的C++工程师

更多精彩&#xff0c;请点击上方蓝字关注我们&#xff01;最近好多同学来找就就说&#xff0c;我想找 xxx 方向的工作&#xff0c;我怎么学习呀&#xff1f;我也不知道这个岗位的招聘要求是啥&#xff1f;这个很正常哈&#xff0c;主要是咱们平时很少去关注企业的招聘要求&…

C语言开发推箱子游戏项目实战

C语言能做什么&#xff1f;相信学过C语言的各位都会有一个疑问&#xff0c;我们学了C语言到底可以做什么&#xff1f;或许有人会说做系统开发、驱动开发等等&#xff0c;但是这个感觉离我们好远&#xff0c;甚至于我们学C语言都仅仅是为了用程序做数学题&#xff0c;要不就是用…

dw php如何传递id参数6,[php] 我的微型论坛的简单教程[已完成]第6/8页

现在数据库中还没有数据&#xff0c;所以&#xff0c;我们运行首页&#xff0c;只显示“对不起&#xff0c;论坛尚在建设中……”。既然我们很希望看到结果&#xff0c;就往数据库中加几条数据吧&#xff01;&#xff01;当然&#xff0c;直接在MySQL客户端运行查询语句"i…

尺度不变性是指什么不变_不变性如何提供帮助

尺度不变性是指什么不变在最近的几篇文章中&#xff0c;包括“ Getters / Setters。 邪恶。 期。” &#xff0c; “对象应该是不可变的”和“依赖注入容器是代码污染者” &#xff0c;我普遍将所有可变对象标记为“ setter”&#xff08;以set开头的对象方法&#xff09;。 我…

java prototype是什么,java设计模式-原型模式(Prototype)

定义原型模式属于对象的创建模式。通过给出一个原型对象来指明所有创建的对象的类型&#xff0c;然后用复制这个原型对象的办法创建出更多同类型的对象。这就是原型模式的用意原型模式的结构原型模式要求对象实现同一个可以“克隆”自身的接口&#xff0c;遮掩个就可以通过赋值…

Windows 动态链接库 DLL 浅析

一、概念DLL&#xff1a;Dynamic Link Library&#xff0c;即动态链接库&#xff0c;这种库包含了可由多个程序同时使用的代码和数据。它是microsoft在windows操作系统中实现共享函数库概念的一种实现方式。其中windows中 一些作为DLL实现的文件有&#xff1a;ActiveX控件&…