I just needed a temporary solution to hold my iPad at my desk. It's worked out pretty well. Thought I'd post the tip:
It's an Office Depot Plate Holder, Clear Item # 544474
Friday, May 28, 2010
Thursday, May 27, 2010
Resetting "Windows XP Mode" to initial settings
Under Windows 7 64-bit ultimate edition, I've had the need to reset my "Windows XP Mode" to initial settings several times over the past few days. Initially I did this because as I used the XP virtual environment, the VHD file grew to around 10 Gig. Not huge, but I wasn't using it for anything except to run a client's 32-bit only VPN software, so it was wasting a fair amount of space. My main machine has a 256 Gig SSD for the main drive, so I am conservative with space consumption.
The second reason was that I was helping my fiancée (a high-school teacher) obtain some (public domain) video for use in her classroom. Unfortunately this video seemed only to be available in a heavily watermarked version on YouTube (ugh) or in a Real Media stream (double-ugh). So I wound up needing to use a mixture of open source and very old software to convert this video to a format that was playable in the classroom. As a rule I don't install software like that on my production machine - a virtual environment is a great "sandbox" for momentary needs like this one. After I converted this video, I no longer needed all these (rather buggy) utilities, so I wanted to start clean.
I didn't see much on the web on how to reset the "Windows XP Mode" to initial settings. I tried this experiment, which worked pretty well.
To reset Windows XP to factory new condition:
Standard cautionary notes:
The second reason was that I was helping my fiancée (a high-school teacher) obtain some (public domain) video for use in her classroom. Unfortunately this video seemed only to be available in a heavily watermarked version on YouTube (ugh) or in a Real Media stream (double-ugh). So I wound up needing to use a mixture of open source and very old software to convert this video to a format that was playable in the classroom. As a rule I don't install software like that on my production machine - a virtual environment is a great "sandbox" for momentary needs like this one. After I converted this video, I no longer needed all these (rather buggy) utilities, so I wanted to start clean.
I didn't see much on the web on how to reset the "Windows XP Mode" to initial settings. I tried this experiment, which worked pretty well.
To reset Windows XP to factory new condition:
- Right click the vmcx file. Select Settings. (On my machine the file is called Windows XP Mode.vmcx and is located in C:\Users\Tom\Virtual Machines)
- Note the location of Hard Disk 1 (On my machine this location is called C:\Users\Tom\AppData\Local\Microsoft\Windows Virtual PC\Virtual Machines\Windows XP Mode.vhd)
- Exit the Settings Dialog
- Delete the files associated with your "Windows XP Mode" environment. On my machine, these are located in C:\Users\Tom\AppData\Local\Microsoft\Windows Virtual PC\Virtual Machines\Windows XP Mode.vhd and are called
- Windows XP Mode.vhd
- Windows XP Mode.vmc
- Windows XP Mode.vmc.vpcbackup
- Windows XP Mode.vsv
- Now, find the original Start Menu shortcut for Windows XP Mode. As long as you've left the Parent Disk in place, the system will prompt you to recreate a new environment:
voilà! - New XP environment (after a few other dialogs and a few minutes building)
- I haven't researched whether this is the "proper" way to do this. But I've done this multiple times on 2 different machines and it takes less than 10 minutes to reset, install anti-virus, and reinstall VPN software
- Obviously when I suggest you delete files on your system, I am assuming you know the implications of this and have everything backed up or have determined that you no longer need anything from the files you are deleting
Tuesday, May 25, 2010
Burn the Ships
Although it's probably an apocryphal story, legend has it that Cortez instructed his men to "Burn the Ships" upon encountering the New World. This has become (in my parlance, anyway) a catchphrase for being irrevocably committed to a particular course of action.
In that spirit, yesterday I blew away v1 of my website and started up this version. This will remain a work in progress for a while, since other client commitments will have me quite busy through June.
Anyone using WordPress who has themes or plugins that they love, please leave a comment.
In that spirit, yesterday I blew away v1 of my website and started up this version. This will remain a work in progress for a while, since other client commitments will have me quite busy through June.
Anyone using WordPress who has themes or plugins that they love, please leave a comment.
Wednesday, April 14, 2010
Time (Not Date) Dimension Table SQL code
I am seeing more call for Time Dimensions. By that I mean Time-of-Day Dimensions. So now I have to retrain myself to call Date Dimensions "Date" and Time Dimensions "Time".
As a follow up to this post, here's some DDL and a quick routine to generate a time of day table. The resolution is to the second, which so far has proved sufficient for my clients' purposes.
Enjoy
SET nocount ON
/*
CREATE TABLE [dbo].[dim_Time](
[TimeId] [int] NOT NULL,
[Time] [time](7) NULL,
[Hours] [tinyint] NULL,
[Minutes] [tinyint] NULL,
[Seconds] [tinyint] NULL,
CONSTRAINT [PK_dim_Time] PRIMARY KEY CLUSTERED
(
[TimeId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
TRUNCATE TABLE [dbo].[dim_Time]
GO
SELECT * FROM dbo.dim_time
*/
DECLARE @second1 INT = 0
DECLARE @currtime TIME
DECLARE @msg VARCHAR(30) = ''
WHILE @second1 < 86400
BEGIN
SELECT @second1 = @second1 + 1
SELECT @currtime = Dateadd(ss, @second1, '00:00.00')
-- SELECT
--DatePart(hh, @currtime) * 10000 +
--DatePart(mi, @currtime) * 100 +
--DatePart(ss, @currtime) AS TimeID
--, @currtime AS [Time]
--, DatePart(hh, @currtime) AS [Hours]
--, DatePart(mi, @currtime) AS [Minutes]
--, DatePart(ss, @currtime) AS [Seconds]
INSERT dbo.dim_time
([TimeID],
[Time],
[Hours],
[Minutes],
[Seconds])
VALUES (
Datepart(hh, @currtime) * 10000 +
Datepart(mi, @currtime) * 100 +
Datepart(ss, @currtime),
@currtime,
Datepart(hh, @currtime),
Datepart(mi, @currtime),
Datepart(ss, @currtime) )
IF @second1 % 1000 = 0
BEGIN
SELECT @msg = 'Now Processing ' + CAST(@second1 AS VARCHAR(12))
PRINT @msg
END
END
As a follow up to this post, here's some DDL and a quick routine to generate a time of day table. The resolution is to the second, which so far has proved sufficient for my clients' purposes.
Enjoy
SET nocount ON
/*
CREATE TABLE [dbo].[dim_Time](
[TimeId] [int] NOT NULL,
[Time] [time](7) NULL,
[Hours] [tinyint] NULL,
[Minutes] [tinyint] NULL,
[Seconds] [tinyint] NULL,
CONSTRAINT [PK_dim_Time] PRIMARY KEY CLUSTERED
(
[TimeId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
TRUNCATE TABLE [dbo].[dim_Time]
GO
SELECT * FROM dbo.dim_time
*/
DECLARE @second1 INT = 0
DECLARE @currtime TIME
DECLARE @msg VARCHAR(30) = ''
WHILE @second1 < 86400
BEGIN
SELECT @second1 = @second1 + 1
SELECT @currtime = Dateadd(ss, @second1, '00:00.00')
-- SELECT
--DatePart(hh, @currtime) * 10000 +
--DatePart(mi, @currtime) * 100 +
--DatePart(ss, @currtime) AS TimeID
--, @currtime AS [Time]
--, DatePart(hh, @currtime) AS [Hours]
--, DatePart(mi, @currtime) AS [Minutes]
--, DatePart(ss, @currtime) AS [Seconds]
INSERT dbo.dim_time
([TimeID],
[Time],
[Hours],
[Minutes],
[Seconds])
VALUES (
Datepart(hh, @currtime) * 10000 +
Datepart(mi, @currtime) * 100 +
Datepart(ss, @currtime),
@currtime,
Datepart(hh, @currtime),
Datepart(mi, @currtime),
Datepart(ss, @currtime) )
IF @second1 % 1000 = 0
BEGIN
SELECT @msg = 'Now Processing ' + CAST(@second1 AS VARCHAR(12))
PRINT @msg
END
END
Sunday, April 4, 2010
Adventures with Virtualization
Those of us needing to run BI software in virtual environments are well familiar with the challenges of getting things running smoothly, especially if you are using a laptop as your lab or demo environment. We have a new set of challenges with Windows 7, and with SharePoint 2010.
Challenge #1 - SharePoint 2010 requires 64 bit OS, and the only MS virtualization software that allows for 64-bit is Hyper-V.
Only problem with running Hyper-V is that you cannot sleep a machine with Hyper-V, so if you’re using you laptop as a lab machine, you need to retain an OS that will run productivity apps and sleep. I set up my old laptop using the technique described here and it works well. I haven’t repeated the process for my new laptop yet, but I plan to.
Challenge #2 - Windows 7 Virtual PC requires Hardware Assisted Virtualization
Apparently this is no longer true, but I've wrestled with this one for months, in fact in early March I returned a machine that didn’t support hardware assisted virtualization because I needed to run Windows 7 VPC. . MS just released a version of Virtual PC that does not require hardware assisted virtualization.
Other tips that have worked well for me:
- Use a fast disk - I was using a 7200 RPM eSATA external drive - faster than the 5400 disk commonly found on laptops. Now I am using an SSD drive- even better.
- Store the VHD in a compressed folder. This one struck me as counter-intuitive but anecdotally seems to work.
Monday, March 22, 2010
Brilliantly stupid MDX debugging technique
Whenever I do something really stupid, rather than keep it to myself, I prefer to blog about it for the entire world to see. Even better - I came up with a debugging technique to save myself from my own, er, stupidity.
The scenario is this: I am developing some SQL Server Analysis Services Date Calculations in MDX for a client. They have three different Date Hierarchies, and wanted the standard, Previous Period, Period to Date, etc calculations. (For a very good explanation of the techniques involved, read this PDF first, then study this refinement from Mosha Pasumansky. )
The MDX looks like this:
Scope([Calculation].[Calculation].[Previous Period]);
([Calendar].[Calendar].[Date]) = ([Calculation].[Current Period], ParallelPeriod([Calendar].[Calendar].[Calendar Year],1));
([Calendar].[Week].[Calendar Week].MEMBERS) = ([Calculation].[Current Period], [Calendar].[Week].Lag(52));
([Calendar].[Calendar].[Calendar Month].MEMBERS) = ([Calculation].[Current Period], [Calendar].[Calendar Month].Lag(12));
([Calendar].[Calendar].[Calendar Quarter].MEMBERS) = ([Calculation].[Current Period], [Calendar].[Calendar Quarter].Lag(4));
([Calendar].[Calendar].[Calendar Year].MEMBERS) = ([Calculation].[Current Period], [Calendar].[Calendar Year].Lag(1));
([Calendar].[NRF].[NRF Week].MEMBERS) = ([Calculation].[Current Period], ParallelPeriod([Calendar].[NRF].[NRF Week],1));
([Calendar].[NRF].[NRF Period].MEMBERS) = ([Calculation].[Current Period], [Calendar].[NRF Period].Lag(13));
([Calendar].[NRF].[NRF Quarter].MEMBERS) = ([Calculation].[Current Period], [Calendar].[NRF Quarter].Lag(5));
([Calendar].[NRF].[NRF Year].MEMBERS) = ([Calculation].[Current Period], ParallelPeriod([Calendar].[NRF].[NRF Year],1));
End Scope;
The scenario is this: I am developing some SQL Server Analysis Services Date Calculations in MDX for a client. They have three different Date Hierarchies, and wanted the standard, Previous Period, Period to Date, etc calculations. (For a very good explanation of the techniques involved, read this PDF first, then study this refinement from Mosha Pasumansky. )
The MDX looks like this:
Scope([Calculation].[Calculation].[Previous Period]);
([Calendar].[Calendar].[Date]) = ([Calculation].[Current Period], ParallelPeriod([Calendar].[Calendar].[Calendar Year],1));
([Calendar].[Week].[Calendar Week].MEMBERS) = ([Calculation].[Current Period], [Calendar].[Week].Lag(52));
([Calendar].[Calendar].[Calendar Month].MEMBERS) = ([Calculation].[Current Period], [Calendar].[Calendar Month].Lag(12));
([Calendar].[Calendar].[Calendar Quarter].MEMBERS) = ([Calculation].[Current Period], [Calendar].[Calendar Quarter].Lag(4));
([Calendar].[Calendar].[Calendar Year].MEMBERS) = ([Calculation].[Current Period], [Calendar].[Calendar Year].Lag(1));
([Calendar].[NRF].[NRF Week].MEMBERS) = ([Calculation].[Current Period], ParallelPeriod([Calendar].[NRF].[NRF Week],1));
([Calendar].[NRF].[NRF Period].MEMBERS) = ([Calculation].[Current Period], [Calendar].[NRF Period].Lag(13));
([Calendar].[NRF].[NRF Quarter].MEMBERS) = ([Calculation].[Current Period], [Calendar].[NRF Quarter].Lag(5));
([Calendar].[NRF].[NRF Year].MEMBERS) = ([Calculation].[Current Period], ParallelPeriod([Calendar].[NRF].[NRF Year],1));
End Scope;
Pretty standard stuff (sorry about the line wraps):
The symptom was that my Calendar Data Hierarchies were working fine, but the other two (Week and NRF [National Retail Federation]) were not. I worked my way through the data, and it all looked correct. Even a dynamic MDX query in SSMS worked fine. But it was wrong in the cube.
When debugging MDX, I find that it pays to go in small increments and to do patently obvious things like setting Scoped statements to constant values, as in:
Scope([Calculation].[Calculation].[Previous Period]);
([Calendar].[Calendar].[Date]) = 7777;
End Scope;
I had done this with this MDX code in an attempt to see what was going on, and it showed me that the scoped overwrites were working, but the calculations they were over-writing with were not. Then I got an idea to change how I was debugging:
Scope([Calculation].[Calculation].[Previous Period]);
([Calendar].[Calendar].[Date]) = 1;
([Calendar].[Week].[Calendar Week].MEMBERS) = 10;
([Calendar].[Calendar].[Calendar Month].MEMBERS) = 100;
([Calendar].[Calendar].[Calendar Quarter].MEMBERS) = 1000;
([Calendar].[Calendar].[Calendar Year].MEMBERS) = 10000;
([Calendar].[NRF].[NRF Week].MEMBERS) = .0001;
([Calendar].[NRF].[NRF Period].MEMBERS) = .001;
([Calendar].[NRF].[NRF Quarter].MEMBERS) = .01;
([Calendar].[NRF].[NRF Year].MEMBERS) = .1;
End Scope;
Essentially I am using a bit-mask, one position for each level. I split the two different hierarchies at the decimal. This allowed me to see which scoped overwrite statement was in effect as I browsed the cube, and it led me to the solution.
It turns out I had defined my scoped overwrite assignment statements in reverse order. (i.e. from highest level (Year) to lowest (day)) Once I switched them so the highest level statement was evaluated last, everything worked as desired. This was a very stupid mistake, and once it was defined as part of the cube MDX script, was a difficult one to spot. Luckily the debugging technique described above made it pretty obvious what was happening.
Wednesday, March 10, 2010
Devils and Angels of BI Architecture
Devil: You don't need to set up a separate star schema database
Angel: Yes you do. We don't want to interfere with the operational systems
Devil: It's sooo much work
Angel: We want to create a simplified schema to benefit our end users
Devil: Phooeh. ETL is BORING
Devil: Just query the source system directly
Devil: What could be better than fresh data
Devil: C'mon the reports not that big
Devil: Everybody's doing it
Intrepid BI Architect: sigh...
Case in point:
This is from an actual email exchange. Names have been changed to protect the innocent.
From: Brave and True BI Developer
Sent: Friday, March 05, 2010 9:33 AM
To: BI Technical Staff
Subject: SSRS Not Responding
Sent: Friday, March 05, 2010 9:33 AM
To: BI Technical Staff
Subject: SSRS Not Responding
Well, this is a new one. I’m on-site at [Dunder-Mifflin] today to do a quick fix on a report and the SSRS instance seems to be refusing to actually render a report. I click on a report that’s been untouched for months with an ultra simple SELECT behind it and the browser just spins with the “Reporting being generated” message in the middle of the browser.
From: Brave and True BI Colleague
Sent: Friday, March 05, 2010 9:34 AM
To: BI Technical Staff
Subject: RE: SSRS Not Responding
From: Brave and True BI Colleague
Sent: Friday, March 05, 2010 9:34 AM
To: BI Technical Staff
Subject: RE: SSRS Not Responding
Check SQL Profiler as you run the report, verify that it is actually reaching the database (with the correct user information, etc.)
From: Brave and True BI Developer
Sent: Friday, March 05, 2010 10:00 AM
To: BI Technical Staff
Subject: RE: SSRS Not Responding
From: Brave and True BI Developer
Sent: Friday, March 05, 2010 10:00 AM
To: BI Technical Staff
Subject: RE: SSRS Not Responding
Got it. There was a transaction open on a table that’s part of a filter on most of the reports. That’s all it was.
______________________________
[My emphasis]
This is why we go to the trouble of setting up an entirely separate system. There should never be a "transaction open on a table that’s part of a filter on most of the reports."
There are times even now when the voices of temptation ring really loud. Usually this occurs in the form of a client or colleague looking at me like I've got two heads when I tell them that we need to spend time building a separate redundant database and ETL to replace a currently running (but poorly performing or problematic) report.
Subscribe to:
Posts (Atom)



