简体   繁体   English

VB6 SQL 2005数据库索引问题

[英]VB6 SQL 2005 Database Index Question

I have a VB app that accesses a sql database. 我有一个访问sql数据库的VB应用程序。 I think it's running slow, and I thought maybe I didn't have the tables propery indexed. 我认为它的运行速度很慢,并且我想也许我没有正确索引这些表。 I was wondering how you would create the indexes? 我想知道您将如何创建索引? Here's the situation. 这是情况。

My main loop is 我的主要循环是

Select * from Docrec 
Order by YearFiled,DocNumb

Inside this loop I have two others databases hits. 在此循环中,我还有另外两个数据库命中。

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

Hopefully I made sense. 希望我有道理。

Try in one query using INNER JOIN: 使用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

You will have only one query to database. 您将只有一个查询到数据库。 The problem can be that you hit database many times and get only one (or few) row(s) per time. 问题可能是您多次访问数据库,而每次仅获得一(或几)行。

Off the top, one thing that would help would be determining if you really need all columns. 最重要的是,将有助于确定您是否真的需要所有列。

If you don't, instead of SELECT *, select just the columns you need - that way you're not pulling as much data. 如果不这样做,请仅选择所需的列而不是SELECT *-这样就不会提取太多数据。

If you do, then from SQL Server Management Studio (or whatever you use to manage the SQL Server) you'll need to look at what is indexed and what isn't. 如果这样做,则需要从SQL Server Management Studio(或用于管理SQL Server的任何工具)中查看索引的内容和未索引的内容。 The columns you tend to search on the most would be your first candidates for an index. 您倾向于搜索最多的列将是您最先选择索引的列。

Addendum 附录
Now that I've seen your edit, it may help to look at why you're doing the queries the way you are, and see if there isn't a way to consolidate it down to one query. 现在,我已经看到了您的编辑内容,这可能有助于查看您为什么按原样进行查询,并查看是否没有将其合并为一个查询的方法。 Without more context I'd just be guessing at more optimal queries. 没有更多的上下文,我只会猜测更多的最佳查询。

I don't know if you need the loop. 我不知道您是否需要循环。 If all you are doing is grabbing the records in maprec that match for docrec and then the same for the second table then you can do this without a loop using inner join syntax. 如果您要做的只是在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)

and then again for the second table... 然后再次进入第二张桌子...

You could also trim up your queries to return only the columns needed instead of returning all if possible. 您还可以整理查询以仅返回所需的列,而不是尽可能返回所有列。 This should help performance. 这应该有助于性能。

To create an index by yourself in SQL Server 2005, go to the design of the table and select the Manage Indexes & Keys toolbar item. 若要在SQL Server 2005中自己创建索引,请转到表的设计并选择“管理索引和键”工具栏项。

You can use the Database Engine Tuning Advisor. 您可以使用数据库引擎优化顾问。 You can create a trace (using sql server profiler) of your queries and then the Advisor will tell you and create the indexes needed to optimize for your query executions. 您可以使用查询创建跟踪(使用sql server profiler),然后Advisor将告诉您并创建优化查询执行所需的索引。

UPDATE SINCE YOUR FIRST COMMENT TO ME: 自您对我的第一评论以来进行更新:

You can still do this by running the first query then the second and third without a loop as I have shown above. 您仍然可以通过运行第一个查询,然后运行第二个和第三个查询而没有循环来执行此操作,如上所述。 Here's the trick. 这是窍门。 I am thinking you need to tie the first to the second and third one hence why you did a loop. 我认为您需要将第一个与第二个和第三个绑定在一起,因此为什么要进行循环。

It's been a while since I have done VB6 recordsets BUT I do recall the ability to filter the recordset once returned from the DB. 自从我完成了VB6记录集以来已经有一段时间了,但是我确实想起了从数据库返回后就可以过滤记录集的功能。 So, in this case, you could keep your loop but instead of calling SQL every time in the loop you would simply filter the resulting recordset data based on the first record. 因此,在这种情况下,您可以保留循环,而不必在循环中每次都调用SQL,而只需根据第一条记录过滤结果记录集数据即可。 You would initialize / load the second & third query before this loop to load the data. 您将在此循环之前初始化/加载第二个和第三个查询以加载数据。 Using the syntax above that I gave will load in each of those tables the matching to the parent table (docrec). 使用上面给出的语法,将在每个表中加载与父表(docrec)的匹配项。

With this, you will still only hit the DB three times but still retain the loop you need to have the parent docrec table traversed so you can do work on it AND the child tables when you do have a match. 这样,您仍将仅命中DB 3次,但仍保留需要遍历父docrec表的循环,以便可以在匹配时对它进行处理,并与子表进行处理。

Here's a few links on ado recordset filtering.... 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 这是有关ado记录集筛选的一些链接。... http://www.devguru.com/technologies/ado/QuickRef/recordset_filter.html http://msdn.microsoft.com/zh-CN/library/ee275540(BTS .10).aspx http://www.w3schools.com/ado/prop_rs_filter.asp

With all this said.... I have this strange feeling that perhaps it could be solved with just a left join on your tables? 话虽如此……我有一种奇怪的感觉,也许只需在您的桌子上左联接即可解决?

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)

this will return all DocRec records AND add all the maprec values and name values where it matches OR NULL if not. 这将返回所有DocRec记录,并将所有maprec值和名称值添加到匹配的位置,否则返回NULL。

If this fits your need it will only hit the DB once. 如果这符合您的需要,它将仅命中数据库一次。

In general looping through records is a poor idea. 通常,遍历记录不是一个好主意。 can you not do a set-based query that gives you everything you need in one pass? 您是否不能一次进行基于集合的查询就可以为您提供所需的一切?

As far as indexing consider any fields that you use in the ordering or where clauses and any fileds that arein joins. 至于索引,请考虑您在排序或where子句中使用的任何字段以及其中的任何文件联接。 Primary keys are indexed as part of the setup of a primary ley but foreign keys are not. 主键被索引为主键设置的一部分,但外键则没有。 Often people forget that they need to index them as well. 人们通常会忘记他们也需要对它们进行索引。

Never use select * in a production environment. 切勿在生产环境中使用select *。 It is a poor practice. 这是一个糟糕的做法。 Do not ever return more data than you need. 永远不要返回超出您需要的数据。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM