【问题标题】:VB6 SQL 2005 Database Index QuestionVB6 SQL 2005 数据库索引问题
【发布时间】:2009-09-09 14:43:28
【问题描述】:

我有一个访问 sql 数据库的 VB 应用程序。我认为它运行缓慢,我想也许我没有索引表。我想知道您将如何创建索引?情况是这样的。

我的主循环是

Select * from Docrec 
Order by YearFiled,DocNumb

在这个循环中,我还有另外两个数据库命中。

Select * from Names 
Where YearFiled = DocRec.YearFiled 
and Volume = DocRec.Volume and Page = DocRec.Page  
Order by SeqNumb


Select * from MapRec
Where FiledYear = DocRec.YearFiled 
and Volume = DocRec.Volume and Page = DocRec.Page 
Order by SeqNumb

希望我说得通。

【问题讨论】:

  • 我已经跟踪到点击名称表的速度。我向由 YearFiled、Volume、Page 和 SeqNumb 组成的 namerec 表添加了一个非聚集索引。同样在这里与 DBA 交谈后,我添加了一个身份作为主键。他还让我将数据库中的数据类型从 char 切换为 varchar。这只是稍微加快了进程。我有一个新问题。不确定我是否应该将其发布为新的?我通常在我的 VB 应用程序中使用变量的数据类型,因为它接受 NULL 值。它们在数据类型之间是否存在性能差异?

标签: sql sql-server sql-server-2005 tsql vb6


【解决方案1】:

使用 INNER JOIN 尝试一个查询:

SELECT * FROM Doctec d
    INNER JOIN Names n ON d.YearField = n.YearField AND d.Volume = n.Volume AND d.Page = n.Page
    INNER JOIN MapRec m ON m.FiledYear = n.YearFiled AND m.Volume = n.Volumen and m.Page = n.Page
ORDER BY YearFiled, DocNumb

您将只有一个对数据库的查询。问题可能是您多次访问数据库,但每次只能获得一(或几)行。

【讨论】:

  • 这将只返回 docrec 中与 Names 和 MapRec 匹配的命中。他的示例显示了遍历所有 docrec 的循环,并在 names 表和 maprec 表中查找每个匹配项。
【解决方案2】:

最重要的是,确定您是否真的需要所有列会有所帮助。

如果您不这样做,而不是 SELECT *,只选择您需要的列 - 这样您就不会提取尽可能多的数据。

如果您这样做了,那么您需要从 SQL Server Management Studio(或您用来管理 SQL Server 的任何工具)中查看哪些已编入索引,哪些未编入索引。您最常搜索的列将是您的第一批索引候选者。

附录
既然我已经看到了您的编辑,这可能有助于了解您为什么按照您的方式进行查询,看看是否没有办法将其合并为一个查询。如果没有更多上下文,我只会猜测更优化的查询。

【讨论】:

    【解决方案3】:

    一般来说,循环遍历记录是一个糟糕的主意。难道你不能做一个基于集合的查询,一次性给你你需要的一切吗?

    就索引而言,请考虑您在排序或 where 子句中使用的任何字段以及连接中的任何字段。主键作为主键设置的一部分被索引,但外键不是。人们经常忘记他们也需要索引它们。

    切勿在生产环境中使用 select *。这是一个糟糕的做法。永远不要返回比您需要的更多的数据。

    【讨论】:

      【解决方案4】:

      我不知道你是否需要循环。如果您所做的只是在 maprec 中获取与 docrec 匹配的记录,然后为第二个表获取相同的记录,那么您可以使用内部连接语法在不循环的情况下执行此操作。

      select columnlist from maprec m inner join docrec d on (m.filedyear = d.yearfield and m.volume = d.volume and m.page=d.page)
      

      然后又是第二张桌子……

      您还可以修剪查询以仅返回所需的列,而不是尽可能返回所有列。这应该有助于提高性能。

      要在 SQL Server 2005 中自己创建索引,请转到表的设计并选择“管理索引和键”工具栏项。

      您可以使用数据库引擎优化顾问。您可以创建查询的跟踪(使用 sql server profiler),然后顾问会告诉您并创建优化查询执行所需的索引。

      自从你第一次对我发表评论后更新:

      您仍然可以通过运行第一个查询然后第二个和第三个不循环来执行此操作,如上所示。这是诀窍。我认为您需要将第一个与第二个和第三个联系起来,因此您为什么要进行循环。

      自从我完成 VB6 记录集以来已经有一段时间了,但我确实记得一旦从数据库返回过滤记录集的能力。因此,在这种情况下,您可以保留循环,但不是每次在循环中调用 SQL,您只需根据第一条记录过滤结果记录集数据。您将在此循环之前初始化/加载第二个和第三个查询以加载数据。使用上面我给出的语法将在每个表中加载与父表 (docrec) 匹配的内容。

      这样,您仍将只访问数据库 3 次,但仍保留遍历父 docrec 表所需的循环,以便您可以在匹配时对其和子表进行处理。

      这里有一些关于 ado 记录集过滤的链接...... http://www.devguru.com/technologies/ado/QuickRef/recordset_filter.html http://msdn.microsoft.com/en-us/library/ee275540(BTS.10).aspx http://www.w3schools.com/ado/prop_rs_filter.asp

      说了这么多....我有一种奇怪的感觉,也许只需在您的表上添加左连接即可解决?

      select * from docrec d
      left join maprec m on (d.YearFiled= m.FiledYear and d.Volume = m.Volume and d.Page = m.Page)
      left join names n on  (d.YearFiled = n.YearFiled and d.Volume = n.Volume and d.Page = n.Page)
      

      这将返回所有 DocRec 记录并添加所有匹配的 maprec 值和名称值,如果不匹配,则为 NULL。

      如果这符合您的需要,它只会访问数据库一次。

      【讨论】:

      • 我需要返回Docrec中的每条记录,不管它在其他表中是否有相应的条目。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-03
      • 1970-01-01
      • 2012-04-25
      • 2011-11-26
      • 2010-11-27
      相关资源
      最近更新 更多