 |
| Edit in Browser | /_layouts/images/icxddoc.gif | /Blogs/U2U/_layouts/formserver.aspx?XsnLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | FileType | xsn | 255 | | Edit in Browser | /_layouts/images/icxddoc.gif | /Blogs/U2U/_layouts/formserver.aspx?XmlLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | ProgId | InfoPath.Document | 255 | | Edit in Browser | /_layouts/images/icxddoc.gif | /Blogs/U2U/_layouts/formserver.aspx?XmlLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | ProgId | InfoPath.Document.2 | 255 | | Edit in Browser | /_layouts/images/icxddoc.gif | /Blogs/U2U/_layouts/formserver.aspx?XmlLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | ProgId | InfoPath.Document.3 | 255 | | Edit in Browser | /_layouts/images/icxddoc.gif | /Blogs/U2U/_layouts/formserver.aspx?XmlLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | ProgId | InfoPath.Document.4 | 255 | | View in Web Browser | /_layouts/images/ichtmxls.gif | /Blogs/U2U/_layouts/xlviewer.aspx?listguid={ListId}&itemid={ItemId}&DefaultItemOpen=1 | 0x0 | 0x1 | FileType | xlsx | 255 | | View in Web Browser | /_layouts/images/ichtmxls.gif | /Blogs/U2U/_layouts/xlviewer.aspx?listguid={ListId}&itemid={ItemId}&DefaultItemOpen=1 | 0x0 | 0x1 | FileType | xlsb | 255 | | Snapshot in Excel | /_layouts/images/ewr134.gif | /Blogs/U2U/_layouts/xlviewer.aspx?listguid={ListId}&itemid={ItemId}&Snapshot=1 | 0x0 | 0x1 | FileType | xlsx | 256 | | Snapshot in Excel | /_layouts/images/ewr134.gif | /Blogs/U2U/_layouts/xlviewer.aspx?listguid={ListId}&itemid={ItemId}&Snapshot=1 | 0x0 | 0x1 | FileType | xlsb | 256 |
|
|
| Edit in Browser | /_layouts/images/icxddoc.gif | /Blogs/U2U/_layouts/formserver.aspx?XsnLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | FileType | xsn | 255 | | Edit in Browser | /_layouts/images/icxddoc.gif | /Blogs/U2U/_layouts/formserver.aspx?XmlLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | ProgId | InfoPath.Document | 255 | | Edit in Browser | /_layouts/images/icxddoc.gif | /Blogs/U2U/_layouts/formserver.aspx?XmlLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | ProgId | InfoPath.Document.2 | 255 | | Edit in Browser | /_layouts/images/icxddoc.gif | /Blogs/U2U/_layouts/formserver.aspx?XmlLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | ProgId | InfoPath.Document.3 | 255 | | Edit in Browser | /_layouts/images/icxddoc.gif | /Blogs/U2U/_layouts/formserver.aspx?XmlLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | ProgId | InfoPath.Document.4 | 255 | | View in Web Browser | /_layouts/images/ichtmxls.gif | /Blogs/U2U/_layouts/xlviewer.aspx?listguid={ListId}&itemid={ItemId}&DefaultItemOpen=1 | 0x0 | 0x1 | FileType | xlsx | 255 | | View in Web Browser | /_layouts/images/ichtmxls.gif | /Blogs/U2U/_layouts/xlviewer.aspx?listguid={ListId}&itemid={ItemId}&DefaultItemOpen=1 | 0x0 | 0x1 | FileType | xlsb | 255 | | Snapshot in Excel | /_layouts/images/ewr134.gif | /Blogs/U2U/_layouts/xlviewer.aspx?listguid={ListId}&itemid={ItemId}&Snapshot=1 | 0x0 | 0x1 | FileType | xlsx | 256 | | Snapshot in Excel | /_layouts/images/ewr134.gif | /Blogs/U2U/_layouts/xlviewer.aspx?listguid={ListId}&itemid={ItemId}&Snapshot=1 | 0x0 | 0x1 | FileType | xlsb | 256 |
|
|
| Edit in Browser | /_layouts/images/icxddoc.gif | /Blogs/U2U/_layouts/formserver.aspx?XsnLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | FileType | xsn | 255 | | Edit in Browser | /_layouts/images/icxddoc.gif | /Blogs/U2U/_layouts/formserver.aspx?XmlLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | ProgId | InfoPath.Document | 255 | | Edit in Browser | /_layouts/images/icxddoc.gif | /Blogs/U2U/_layouts/formserver.aspx?XmlLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | ProgId | InfoPath.Document.2 | 255 | | Edit in Browser | /_layouts/images/icxddoc.gif | /Blogs/U2U/_layouts/formserver.aspx?XmlLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | ProgId | InfoPath.Document.3 | 255 | | Edit in Browser | /_layouts/images/icxddoc.gif | /Blogs/U2U/_layouts/formserver.aspx?XmlLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | ProgId | InfoPath.Document.4 | 255 | | View in Web Browser | /_layouts/images/ichtmxls.gif | /Blogs/U2U/_layouts/xlviewer.aspx?listguid={ListId}&itemid={ItemId}&DefaultItemOpen=1 | 0x0 | 0x1 | FileType | xlsx | 255 | | View in Web Browser | /_layouts/images/ichtmxls.gif | /Blogs/U2U/_layouts/xlviewer.aspx?listguid={ListId}&itemid={ItemId}&DefaultItemOpen=1 | 0x0 | 0x1 | FileType | xlsb | 255 | | Snapshot in Excel | /_layouts/images/ewr134.gif | /Blogs/U2U/_layouts/xlviewer.aspx?listguid={ListId}&itemid={ItemId}&Snapshot=1 | 0x0 | 0x1 | FileType | xlsx | 256 | | Snapshot in Excel | /_layouts/images/ewr134.gif | /Blogs/U2U/_layouts/xlviewer.aspx?listguid={ListId}&itemid={ItemId}&Snapshot=1 | 0x0 | 0x1 | FileType | xlsb | 256 |
|
|
|
 |
|
|
|
|
|
|
|
3/04/2009Profiler is a handy tool to find out what is happening on your server. Since SQL Server 2005, this tool can also be used to analyze Analysis Services. I’m pleased to see that many people start using this tool, and save the profiler traces into text files, since this is faster than storing them directly in a table (remember, databases are one of the slower mechanisms to store data in: security, reliability, they all come at the price of performance: a stupid binary file is not secure nor reliable, but it is faster to write to). The problem however is that you need to upload these trace files into a relational table afterwards if you want to query them easily. For trace files coming from tracing the relational database, there is a nice table valued function fn_trace_gettable that helps you loading the data in a table. Unfortunately, this function doesn’t work for trace files from Analysis Services. But there is a manual workaround: load the trace file in the profiler, and then use the Save As functionality of the profiler, where you can save in a relation table:
 24/03/2009In Business Intelligence, meta-data is very important. SQL Server Analysis Services documenter is a tool which extracts meta-data out of an Analysis Services database (OLAP and data mining), such that documentation can be generated from the database, instead of having outdated documentation which is stored outside the database. A few days ago, we released the new version, where the most important improvements are: - Support for both 2005 and 2008 versions of Analysis Services
- KPIs and Actions included in the documentation
So, dive into our resource center, and download your free copy. Have fun! Nico 26/09/2008That was the question I recently got from a customer: they had two systems which send comparable queries to the same SQL Server database, and the system using ADO.Net was 'significantly slower' than the other system. OK, first thing to do if such a question pops up is to run the profiler to measure the difference. And indeed, we saw two queries retrieving the same data, but the one from ADO.Net was more than a factor 20 slower than the other. Very striking was the huge number of page requests (page reads in profiler, or using SET STATISTICS IO ON): the fast query accessed about 100 pages, the ADO.Net one read more than 15000 pages! The fast query is exec sp_executesql N'SELECT * FROM dbo.adonetdemo WHERE trackingstring = ''4E0A-4F89-AE''' The ADO.Net query is exec sp_executesql N'SELECT * FROM dbo.adonetdemo WHERE trackingstring = @trackingid', N'@trackingid NVARCHAR', @trackingid = '4E0A-4F89-AE' My first guess was: wrong execution plan. Either outdated statistics or wrong execution plans can cause a lot of unnecessary data access... So we looked at the execution plans (in Management studio, Ctrl+M and running the query) and noticed... no immediate difference! Both queries used the same indexes in the same order: first the non-clustered index on trackingstring to resolve the where clause, then doing a lookup in the clustered index to retrieve all the columns on the selected row (select *): The problem identified The only indication that something weird was going on, was that the cost of the row lookup was estimated at 93% of the cost in the fast query, and only 9% of the cost in the slow ADO.Net query. Only upon closer investigation of the execution plan, we noticed a small but important difference: the slow query did use an implicit operator: converting the trackingstring column (of type varchar) to nvarchar. In other words, it picked the smallest index that contained the varchar column, and converted every string to nvarchar before comparing it with the varchar parameter we provided in the query! The real problem was the ADO.Net code, which looked like this: cmd.CommandText = "SELECT * FROM dbo.adonetdemo WHERE trackingstring = @tstring"; cmd.Parameters.AddWithValue("tstring","4E0A-4F89-AE"); Since strings in .Net are unicode, these types are mapped onto NVARCHAR, and if the underlying column happens to be of type VARCHAR, SQL Server will convert the full column to NVARCHAR before using the comparison operator, on every query again! This causes a lot of unnecessary IO, if we know that the input string can easily be written as VARCHAR. In other words: dropping the N from the NVARCHAR variable declaration improved the performance of our query by at least a factor 20! The solution There is nothing wrong with ADO.Net if you use it in the right way, but as the above example illustrates, it is easy to shoot yourself in the foot if you don't pay attention. For this example, there are three solutions which would have avoided the problem: - Using stored procedure: if our query was embedded in a stored proc with a VARCHAR parameter, no harm would be done.
- Using typed datasets: if we had used typed datasets and/or typed table adapters, these would have queried the table metadata before and would have generated the right queries. Be careful though if you later on change a type from NVARCHAR to VARCHAR without regenerating the typed TableAdapters.
- Setting the parameter type in .Net: the Parameter objects in a SqlCommand have a DbType property, with which we can signal the appropriate type:
cmd.CommandText = "SELECT * FROM dbo.adonetdemo WHERE trackingstring = @tstring"; cmd.Parameters.AddWithValue("tstring","4E0A-4F89-AE"); cmd.Parameters[0].DbType = System.Data.DbType.AnsiString; Nico Jacobs 20/06/2008In Reporting Services 2005 we have document maps which creates an interactive table of content (TOC): every entry is a hyperlink. Nice for interactive use, but nearly useless when you render your report for printing. In print, we want page numbers, which is very, very hard to get in SSRS2005. In Reporting Services 2008, it is still very hard to get a TOC with page numbers... unless you render to Word! So, go ahead, deploy the Adventureworks Sample reports, open up the Product Catalog report and verify it has a document map in it. Next, export this to a Word file (it uses Word 2000, which can easily be used by Office 2002, 2003 and 2007 as well). Open up the Word file. There is no TOC in there, but we can create one explicitly. Only, do not be to hasty! If you create a regular TOC, it will use the Heading styles to place them in the TOC, and the Word export does not have Heading styled elements. So we have to create the TOC. In Word 2007, go to the References ribbon, click the Table Of Content button, and select Insert table of content. Next, click the Options... button, and in there, deselect Styles and select Table entry fields. Next, click twice the OK button and enjoy your TOC! 
7/01/2008Best wishes for 2008! And for those who are using Microsoft's OLAP and data mining database, analysis services, we have a new year's gift for you: a new release of our documentation generation tool. We added support for data mining structures and data mining models, so that they show up in the generated HTML documentation as well. Have fun! Nico (PS: download it at http://www.u2u.be/res/SQL05_ASDoc.aspx) 2/11/2007Many applications have a search functionality. In such a case, we would like an approximate (or fuzzy) search, which returns all items that are similar (in stead of identical) to the item we're looking for. In the past days, I developped a library which implements this for Linq (Language INtergated Query) to objects. So, all you .Net 3.5 programmers out there that need approximate search, download this dll from our website and get started! Basically, the library adds two methods to LINQ: ProximitySort and ProximitySearch. The first one sorts all objects in the collection based on how similar they are to a given object, so it returns a collection. The second one returns only the best match. Because of this limitation, it can apply some optimisations. In short, ProximitySearch is conceptually similar to ProximitySort(...).First(), only more performant. Both methods are based on string comparison: they just apply the ToString method on every object in the collection, and then calculate a distance between this string and the string of the SearchTerm object. The distance used is the Lhevenstein distance, a variant of the edit distance. These distances are language independant, they work on names, product numbers,... . If you want to compare objects on some other string than the one returned by ToString, there is an extra overload which allows you to specify a string selector. Let's show some sample code. "A few minutes ago somebody called with a complaint on the order he made on 10/5/2007, his name was 'Peterson' or something like that..." var allShoppers = from c in Customers where c.Orders.OrderDate = "10/5/2007" select c; var peterson = allShoppers.ProximitySearch("Peterson", c => c.CustomerName); First we retrieve all people who bought something on that particular day (allShoppers), then we filter out the single person who's customername looks most like 'Peterson'. "On our website, customers hate that huge drop down box which contains all our product names, but when we let them select a product category first, the complain that they don't know in which category to look... What can we do?" Product searchProduct = new Product(); searchProduct.Name = textbox.Text; var similarProd = Products.ProximitySort(searchProduct).Take(10); If Product has a ToString method that shows the productname, and textbox.Text contains the name of the product the user is searching for, then the similarProd collection will contain all the products who's name resembles the one the user typed. Show them in a drop down box and let the user select from that limited box. Have fun with the linq extensions! If I find some time next week (I'll be at TechEd) I'll post a follow-up article with some best practises and timings. 31/10/2007Before we get to the bad part, I first want to stress the importance of the new declarative management framework (DMF). It allows administrators to define policies (naming conventions, security settings, force index creation, avoid fragmented data,...) and then map these policies onto servers or databases. This will simplify the administration of a SQL server instance a lot! For more info, check e.g. this webcast. Now for the bad news. Policies are grouped into policy groups (quite straight forward), and a database subscribes to zero, one or more policy groups. However, when we drop a database, the subscriptions are not dropped. This can cause some very nasty side effects: - When dropping a subscription group, this operation can fail because of a subscription by a database you dropped already a while ago. In this case, manually dropping the subscriptions will solve the problem.
- Imagine you drop a database X which subscribed to a bunch of policies. Some months later you create a new database which accidently has the same name X. Then automatically all policies which applied to your old database X will now also apply to your new database X: Mapping happens on database name, not id!
What do we do about this? This behaviour is in the July CTP, maybe next releases will no longer suffer from this problem (vote for the bug report here). Else, the solution is to manually clean up these subscriptions. In the msdb database, you find a view syspolicy_policy_group_subscriptions and a stored procedure sp_syspolicy_delete_policy_group_subscription with wich you can manually fix all problems. Nico 16/10/2007Today we release a new version of our best practise checker. Version 1.1 now checks for 28 best practises, nearly ten times more than the previous release. To give a bit of an impresion, we mention a few of the tests: - Are you using the most efficient SQL Server data provider?
- Do your attributes have appropriate keys?
- Are you using OrderBy and UnkownMember appropriately? The default settings are not always the best setting for these properties...
- Are your hierarchies designed in a propper way?
- Did you put distinct counts in separate measure groups?
- Are your partitions reasonable in size?
- Did you design reasonable aggregates?
We also improved the user interface. You can export the detected violations into comma separated value (csv) or xml format, and import them later in the tool. Very handy to upload the information in Excel or a relational database. You can also generate reports on the detected violations. These reports can be viewed on-screen or exported to Excel or pdf. A new option is to annotate a best practise violation. You can also mark a violation as 'Ignore': like most best practises, sometimes you might have good reasons to ignore a violation: the exceptions to the rules... It is also possible to include multiple databases and historical checks in a single analysis. As you see, a lot of improvements. To download this tool, check our website. Nico 16/08/2007We updated our tool which generates HTML documentation from live OLAP cubes on analysis services 2005. The new version allows for generating documentation with multiple levels of detail, as well as collapsable web pages for easier interactive use. And to help the management: it became a click-once application! Check it out at http://www.u2u.be/res/SQL05_ASDoc.aspx
Nico Analysis Services, Microsofts OLAP and Data Mining engine, is a very powerful tool. But like many powerfull tools, if you don't configure it in the right way, it impacts the performance. There are a bunch of 'best practises', but now there is also a tool which automatically checks these.
Analysis Services Best Practise Analyser checks your live OLAP databases against some key Best practises. Currently, it checks for aggregations, attribute relationships and non-empty behavior on calculations, but we plan to add more in the future. Try it out for free!
Nico
| Edit in Browser | /_layouts/images/icxddoc.gif | /Blogs/U2U/_layouts/formserver.aspx?XsnLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | FileType | xsn | 255 | | Edit in Browser | /_layouts/images/icxddoc.gif | /Blogs/U2U/_layouts/formserver.aspx?XmlLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | ProgId | InfoPath.Document | 255 | | Edit in Browser | /_layouts/images/icxddoc.gif | /Blogs/U2U/_layouts/formserver.aspx?XmlLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | ProgId | InfoPath.Document.2 | 255 | | Edit in Browser | /_layouts/images/icxddoc.gif | /Blogs/U2U/_layouts/formserver.aspx?XmlLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | ProgId | InfoPath.Document.3 | 255 | | Edit in Browser | /_layouts/images/icxddoc.gif | /Blogs/U2U/_layouts/formserver.aspx?XmlLocation={ItemUrl}&OpenIn=Browser | 0x0 | 0x1 | ProgId | InfoPath.Document.4 | 255 | | View in Web Browser | /_layouts/images/ichtmxls.gif | /Blogs/U2U/_layouts/xlviewer.aspx?listguid={ListId}&itemid={ItemId}&DefaultItemOpen=1 | 0x0 | 0x1 | FileType | xlsx | 255 | | View in Web Browser | /_layouts/images/ichtmxls.gif | /Blogs/U2U/_layouts/xlviewer.aspx?listguid={ListId}&itemid={ItemId}&DefaultItemOpen=1 | 0x0 | 0x1 | FileType | xlsb | 255 | | Snapshot in Excel | /_layouts/images/ewr134.gif | /Blogs/U2U/_layouts/xlviewer.aspx?listguid={ListId}&itemid={ItemId}&Snapshot=1 | 0x0 | 0x1 | FileType | xlsx | 256 | | Snapshot in Excel | /_layouts/images/ewr134.gif | /Blogs/U2U/_layouts/xlviewer.aspx?listguid={ListId}&itemid={ItemId}&Snapshot=1 | 0x0 | 0x1 | FileType | xlsb | 256 |
|
|
|
|
|
|
|
|