改进 SQL 查询 xpath 评估
Improve SQL query for xpath Evaluating
数据库
我有用于保存 XML 文档的数据库。
数据库如下所示:
所以我可以将任何 XML 文件保存到我的通用数据库中。
XPath 查询
然后我将 XPATH 查询转换为 SQL 查询,用于选择元素。
- 已翻译的 xpath 查询示例:
1) //EMPTY[./PERIOD]
SELECT e2.docId
, e2.startPos
, e2.endPos
, p2.NodeName
, p2.levelEl
, p2.pathID
From Path p2
, Element e2
, Path p3
, Element e3
WHERE e2.docID = p2.docID
AND e2.pathID = p2.pathID
AND p2.NodeName = 'EMPTY'
AND p2.levelEl >= 1
AND e3.docID = p3.docID
AND e3.pathID = p3.pathID
AND p3.NodeName = '_PERIOD_'
AND e2.startPos < e3.startPos
AND e2.endPos > e3.endPos
AND e2.docId = e3.docId
AND p2.levelEl = p3.levelEl - 1
AND e2.docId
= 3147524262 GROUP BY e2.docId
, e2.startPos
, e2.endPos
, p2.NodeName
, p2.levelEl
, p2.pathID
ORDER BY startPos;
2) //EMPTY[./PERIOD]/S/NP
SELECT e5.docId
, e5.startPos
, e5.endPos
, p5.NodeName
, p5.levelEl
, p5.pathID
From Path p2
, Element e2
, Path p3
, Element e3
, Path p4
, Element e4
, Path p5
, Element e5
WHERE e2.docID = p2.docID
AND e2.pathID = p2.pathID
AND p2.NodeName = 'EMPTY'
AND p2.levelEl >= 1
AND e3.docID = p3.docID
AND e3.pathID = p3.pathID
AND p3.NodeName = '_PERIOD_'
AND e2.startPos < e3.startPos
AND e2.endPos > e3.endPos
AND e2.docId = e3.docId
AND p2.levelEl = p3.levelEl - 1
AND e4.docID = p4.docID
AND e4.pathID = p4.pathID
AND p4.NodeName = 'S'
AND e2.startPos < e4.startPos
AND e2.endPos > e4.endPos
AND e2.docId = e4.docId
AND p2.levelEl = p4.levelEl - 1
AND e5.docID = p5.docID
AND e5.pathID = p5.pathID
AND p5.NodeName = 'NP'
AND e4.startPos < e5.startPos
AND e4.endPos > e5.endPos
AND e4.docId = e5.docId
AND p4.levelEl = p5.levelEl - 1
AND e5.docId
= 3147524262 GROUP BY e5.docId
, e5.startPos
, e5.endPos
, p5.NodeName
, p5.levelEl
, p5.pathID
ORDER BY startPos;
问题
正如我们所看到的,对于 xpath 中的每个其他节点,我将 table element 和 path 添加到FROM 语句,表示该节点,带有一些 where 条件来确定该节点应位于何处。
- Table 元素 大约有 145 000 行。
- Table path 大约有 41 000 行。
问题是,查询 1) 运行得非常快,但是对于每个新节点,sql 都要慢得多。例如,查询 1) 需要 24 毫秒,但查询 2) 运行大约 5 分钟。
我添加了索引,因此查询计划仅使用索引查找(根据 Microsoft sql 服务器)。
问题
您是否知道如何生成 SQL 查询以加快执行速度的任何解决方案?或者对现有查询进行一些改进(DB table 引擎等)?
我正在从 Xpath 创建树,看起来像这样
ROOT-ROOT (type: ROOT) False
//-EMPTY (type: NODE) False
/-_PERIOD_ (type: NODE) False
/-S (type: NODE) False
/-NP (type: NODE) True
然后我从那棵树生成 SQL
有一个 lot of research on this topic and your approach will inevitably lead to a lot of self joins which is slow. It is very close to this solution. I recommend you to use some native XQuery database such as BaseX, or Saxon 本身经过优化,可以处理 XQuery 而无需将它们重写到 SQL 中。
但是,如果您真的想将 XQueries 重写为 SQL,那么请阅读例如 XPath accelerator proposed by Torsten Grust. Ideas behind his work are implemented in MonetDB XQuery engine。他使用的标签方案与您略有不同,但我想这些想法也可以在您的方法中实现。
数据库
我有用于保存 XML 文档的数据库。 数据库如下所示:
所以我可以将任何 XML 文件保存到我的通用数据库中。
XPath 查询
然后我将 XPATH 查询转换为 SQL 查询,用于选择元素。
- 已翻译的 xpath 查询示例:
1) //EMPTY[./PERIOD]
SELECT e2.docId
, e2.startPos
, e2.endPos
, p2.NodeName
, p2.levelEl
, p2.pathID
From Path p2
, Element e2
, Path p3
, Element e3
WHERE e2.docID = p2.docID
AND e2.pathID = p2.pathID
AND p2.NodeName = 'EMPTY'
AND p2.levelEl >= 1
AND e3.docID = p3.docID
AND e3.pathID = p3.pathID
AND p3.NodeName = '_PERIOD_'
AND e2.startPos < e3.startPos
AND e2.endPos > e3.endPos
AND e2.docId = e3.docId
AND p2.levelEl = p3.levelEl - 1
AND e2.docId
= 3147524262 GROUP BY e2.docId
, e2.startPos
, e2.endPos
, p2.NodeName
, p2.levelEl
, p2.pathID
ORDER BY startPos;
2) //EMPTY[./PERIOD]/S/NP
SELECT e5.docId
, e5.startPos
, e5.endPos
, p5.NodeName
, p5.levelEl
, p5.pathID
From Path p2
, Element e2
, Path p3
, Element e3
, Path p4
, Element e4
, Path p5
, Element e5
WHERE e2.docID = p2.docID
AND e2.pathID = p2.pathID
AND p2.NodeName = 'EMPTY'
AND p2.levelEl >= 1
AND e3.docID = p3.docID
AND e3.pathID = p3.pathID
AND p3.NodeName = '_PERIOD_'
AND e2.startPos < e3.startPos
AND e2.endPos > e3.endPos
AND e2.docId = e3.docId
AND p2.levelEl = p3.levelEl - 1
AND e4.docID = p4.docID
AND e4.pathID = p4.pathID
AND p4.NodeName = 'S'
AND e2.startPos < e4.startPos
AND e2.endPos > e4.endPos
AND e2.docId = e4.docId
AND p2.levelEl = p4.levelEl - 1
AND e5.docID = p5.docID
AND e5.pathID = p5.pathID
AND p5.NodeName = 'NP'
AND e4.startPos < e5.startPos
AND e4.endPos > e5.endPos
AND e4.docId = e5.docId
AND p4.levelEl = p5.levelEl - 1
AND e5.docId
= 3147524262 GROUP BY e5.docId
, e5.startPos
, e5.endPos
, p5.NodeName
, p5.levelEl
, p5.pathID
ORDER BY startPos;
问题
正如我们所看到的,对于 xpath 中的每个其他节点,我将 table element 和 path 添加到FROM 语句,表示该节点,带有一些 where 条件来确定该节点应位于何处。
- Table 元素 大约有 145 000 行。
- Table path 大约有 41 000 行。
问题是,查询 1) 运行得非常快,但是对于每个新节点,sql 都要慢得多。例如,查询 1) 需要 24 毫秒,但查询 2) 运行大约 5 分钟。
我添加了索引,因此查询计划仅使用索引查找(根据 Microsoft sql 服务器)。
问题
您是否知道如何生成 SQL 查询以加快执行速度的任何解决方案?或者对现有查询进行一些改进(DB table 引擎等)?
我正在从 Xpath 创建树,看起来像这样
ROOT-ROOT (type: ROOT) False
//-EMPTY (type: NODE) False
/-_PERIOD_ (type: NODE) False
/-S (type: NODE) False
/-NP (type: NODE) True
然后我从那棵树生成 SQL
有一个 lot of research on this topic and your approach will inevitably lead to a lot of self joins which is slow. It is very close to this solution. I recommend you to use some native XQuery database such as BaseX, or Saxon 本身经过优化,可以处理 XQuery 而无需将它们重写到 SQL 中。
但是,如果您真的想将 XQueries 重写为 SQL,那么请阅读例如 XPath accelerator proposed by Torsten Grust. Ideas behind his work are implemented in MonetDB XQuery engine。他使用的标签方案与您略有不同,但我想这些想法也可以在您的方法中实现。