Thursday, January 9, 2014

Pencil Project as an alternative to Visio for IT professionals

Pencil Project advertises itself as an open source Graphical User Interface (GUI) prototyping tool.  The project stresses it's available for "All" platforms.  "All" platforms includes Windows, Mac, and Linux (Fedora package).

 

(Installed version | Portable Version)

 

As my career has progress in roles such as developer, database administrator, project manager, or analyst, I have always used the software Microsoft Visio.  My first experience with it was in college when Visio was made by a separate company, before being acquired by Microsoft.  I have always carried it with me, buying my own license when working for small companies, and using an enterprise license more recently. 

 

As much as Microsoft Visio has been help, it does have limitations.  The software is not always 'with you', or may be unattainable or inaccessible to other team members due to licensing issues.

 

Pencil Project in a portable version can be carried on your portable drive or cloud drive.

 

Business Analysis

Pencil Project has a basic, but complete Flowcharting shapes available.  Connectors allow basic connections between shapes and stay connected as the diagram is arranged.

 

 

There are three simple connector choices:

 

Database

Pencil Project contains no templates or Shapes for representing Data or Database objects.  Another diagramming tool is necessary.

 

UI prototyping

Extensive templates and shapes for popular Uis.

 

 

Thursday, December 26, 2013

SQL Server 2012 AlwaysOn Availability Group - My experience with a proof-of-concept

Just had my experience building our organization's first SQL Server 2012 AlwaysOn Availability Group.  This is a proof-of-concept environment that will be used to demonstrate if we should build out this environment across physical locations.  This post summarizes the resources used in this initial build.
 
The white papers from Microsoft were the more comprehensive resource.   Used these when planning, and justifying the proof-of-concept.
 
Once it got time to actually build, these step-by-steps guides or checklists were used:
 
Here were some of the issues I ran into, and lessons learned
 
Separation of Duties - Server Administration and Database Administration
In my organization, there is a separate Server team controlling virtualization and Server OS while the 'Database' team has full rights to the database software.  Our first build required some back-and-forth collaboration to resolve issues that went above and beyond a standard database server
Lessons learned:
Setup up through the Windows Server Failover Cluster step mostly involves the Server Administration role.  Expect some collaboration needed between Server Administration and Database Administration in new environments
 
AlwaysOn Availability Group configuration
The AlwaysOn Availability Group configuration itself was extremely straight-forward.  The issues I ran into turned out to be items that, either by habit or due the environment, were overlooked when creating a test.  Might not run into these in production with the stricter controls on individual SQL Server instances
 
Note that the database to be made 'AlwaysOn' should be attached or restored to the 'Primary' SQL Server instance in the cluster.  During the AlwaysOn group creation, it can be restored to any secondary instances. 
Lessons learned:
Assess the SQL Server instances to be included in an AlwaysOn group against the standard build for a standalone SQL Server in production.
 

Monday, July 29, 2013

Fixup Script for conflict tables on a Transactional Replication

This script fixes up the conflict tables generated by a transactional replication subscription, and marks them as system tables.

In SQL Server replication, a subscription to a publication of the type 'Transactional replication with updatable subscriptions' allow edits on the subscriber. Conflicts in those edits (e.g. a record modified at the subscriber and publisher) have to be resolved. The default setting is 'Keep the publisher change'. If a given subscriber is on the losing side of the change, conflicts are stored on the subscribers and can be viewed through the Conflict Viewer on the subscriber. They are stored in conflict tables per publication, per table in the format 'dbo.conflict_{PublicationName}_{TableName}. These tables are system tables.

In the scenario that led to the need for this script, both of the servers was patched to SQL Service Pack 2, and replication stopped and restarted. At some point during the process, the conflict tables showed as User Tables. While replication did work continue successfully, having the tables as User Tables was problematic. For starters, permission grants or scripts that target all user tables risked allowing edits to these replication tables, and the Object Explorer view in SSMS became quite messy.

Before

After

Limited testing for this has occurred - basically confirmed successful insert, update, and delete transactions before and after running this script.

Please note much credit for assisting in finding the underlying symptoms and general brainstorming should go to all the people at @SacSQLUG, and @SQLSoldier

SQL

Edit|Remove

/*

FixupConflictTables

 

Will examine the conflict tables generated by a transactional replication subscription, and mark them 

as system tables if for some reason they are showing up as User Tables

*/

--set this constant to have this script perform the action, otherwise it will output the resulting script only

DECLARE @ExecuteNow bit

SET @ExecuteNow = 0

 

--find the name of the associated publication

DECLARE @Publication sysname

SELECT @Publication = publication FROM dbo.MSreplication_subscriptions

 

PRINT '--Fix up conflict tables for the publication ' + @Publication

 

--buffers to hold SQL statements

DECLARE @SQL nvarchar(4000)

SET @SQL =''

DECLARE @tablename sysname

 

--loop through the tables that look like 'conflict_{Publication}_{tablename) and aren't marked as MS shipped (i.e. system objects)

DECLARE curConflictTables CURSOR LOCAL FAST_FORWARD READ_ONLY FOR

SELECT name FROM sys.tables WHERE name LIKE 'conflict_' + @Publication + '_%'

    AND is_ms_shipped = 0

 

OPEN curConflictTables

FETCH NEXT FROM curConflictTables INTO @tablename

 

WHILE @@FETCH_STATUS = 0

BEGIN

    --build the sql to convert this to a system table

    SET @SQL = 'sys.sp_MS_marksystemobject ''' + @tablename + ''''

     

    PRINT @SQL

    IF @ExecuteNow = 1 

        EXECUTE sp_executesql @SQL

 

    FETCH NEXT FROM curConflictTables INTO @tablename

END

 

-- close a cursor

CLOSE curConflictTables

DEALLOCATE curConflictTables

 

Tuesday, April 23, 2013

WinDirStat for SQL Server DBAs

WinDirStat can be used to quickly assess the drive usage by focusing on the relative usage of the drive.   As a SQL Server DBA, disk volume and usage may not be your direct purview, but undoubtedly it can affect you.  Usually it will affect you at the worst time: The disk is full and SQL Server database and supporting files are to blame.  The immediate task affecting the DBA will be to get the disk usage under control - this requires you to assess how to quickly recover disk space in low risk areas.   A follow-on task to such an issue will be to then assess capacity and make recommendations.  WinDirStat is a free, open source tool that can help in these situations.

The three pane layout of WinDirStat allows you to simultaneously see and compare the following aspects: 
  • Relative Size per folder
  • Relative Size per file type
  • Proportional graphical view of each file

For example, in the below screen shot, a drive was nearly 99% full.  This is a simple example because the drive is organized very well already and has a very specific use.  It becomes clear quickly that the folder 'SQLLogs' uses the most space, that the 'LDF File' file type or 'SQL Server Log File' is the file type at issue.  And through the graphical view, you can quickly click and assess that the largest file is a particular log file that has grown to 118 GB.

Example #1:

This is a simple example because the drive is organized very well already and has a very specific use.  It becomes clear quickly that the folder 'SQLLogs' uses the most space, that the 'LDF File' file type or 'SQL Server Log File' is the file type at issue.  And through the graphical view, you can quickly click and assess that the largest file is a particular log file that has grown to 118 GB.

In this example, a more multipurpose volume on a development server, seeing the three aspects (by folder, by file type, and the graphical view) showed a more nuanced picture. 

Example #2:

The largest folder is the 'BackupsMonthly'.  The largest file type was 'BAK File' - SQL Server Backups.  Clicking the large blue squares revealed the largest SQL Server Backups.  But in this case, those files were relatively stable in size, that is, a certain amount of backup files were necessary. 

Secondarily, this revealed a large usage of the Recycle Bin (@RECYCLE.BIN) which was easily cleaned.  Also a few large disk images ('ISO' shown as associated with 'Virtual CloneDrive' in the image above) related to software that was a candidate to be relocated to another server.

How to get WinDirStat
WinDirStat is a free, open source tool.  It can be downloaded from WinDirStat.info.  Since it is open source, the program can be modified or extended and through the folks at PortableApps.com, there is a portable version available.

I recommend acquiring the portable version of WinDirStat.  Portable WinDirStat requires no installation, so the files can simply be copied - on your workstation, a network shared folder, or onto your SQL Servers themselves


Wednesday, December 12, 2012

Alternatives to handling null values in aggregate functions or How to avoid the "Warning: Null value is eliminated by an aggregate or other SET operation."

Most SQL developers have written many queries that perform calculations using aggregate functions such as SUM() or COUNT().  Many have not thought deeply about the what is happening within that aggregate function, and lesser so deeply about the handling of NULL values.  While typically, the developer should not have to think deeply about such internals, there is a situation where it might rise to your attentions.   When you see the "Warning: Null value is eliminated by an aggregate or other SET operation".

In most querying activities, the "Warning: Null value is eliminated by an aggregate or other SET operation" wouldn't bubble up to your attention.  In SQL Server Management Studio, you might notice if you click over to the 'Messages' tab:
This appears on an otherwise working query. 

There is a situation where this demands developer attention, when it is encountered in a SQL Server Integration Services package.  A Microsoft Connect-reported issue describes the scenario where "
An SSIS package which runs fine but sporadically fails with "Warning: Null value is eliminated by an aggregate or other SET operation" (Bug 483175). 

This can occur when the query for a Source Adapter is written in such a way that it aggregates potentially Null values, either directly or through dependent objects.

Microsoft has weighed in with "The real problem is why the underlying OLEDB provider returns a failure code then. Probably the warning is related but not necessary. The specific warning can happen to be there."  Agree or disagree with the resolution to that, the reality is something about the query in the Source Adapter that will have to change.   The following is a very simple example of the scenario, and two alternatives to change the query such that OLEDB warning will no longer occur.

The requirement from the script was a result set that will count the not null values.

The first step in the script is to setup a very simple table variable.  Without specifying anything for the column beyond the name and data type, it will allow Null values.  The script then inserts two legitimate values, one Null value, then one zero.  This will be sufficient to demonstrate that different logical results are gathered by counting rows, by counting a column, and by summing.

DECLARE @tst TABLE
(
VALUE int
)

INSERT INTO @tst (Value) VALUES (1)
INSERT INTO @tst (Value) VALUES (7)
INSERT INTO @tst (Value) VALUES (NULL)
INSERT INTO @tst (Value) VALUES (0)

SELECT * FROM @tst

The first test is the query most developers would naturally right.  You might have even built this through the Query Designer:

SELECT COUNT(*) AS CountOfRows, COUNT(value) AS CountOfValues, SUM(value) AS SumOfValues FROM @tst


Results meet requirements, the 'CountOfValues' clearly returns the '3' legitimate values.  The 'CountOfRows' and 'SumOfValues' are true for what they are, but neither can be used to gain any insight into the number of non-null values.  Back on the 'Messages' tab, though, the Warning about null values appears - this is the type of query that will cause an SSIS Source Adapter to raise an exception.

What's happening here?   Basically, this query is relying on the database management systems handling of null values in a certain way, instead of having the query itself specify how nulls should be handled.  The ANSI-SQL 92 standard specifies that warnings be raised in the case of aggregate functions that rely on the elimination of null values before completing. (Gotcha! SQL Aggregate Functions and NULL has deep discussion on this topic)  The implication is that a given database management system might handle null values differently, or the handling could be set through configuration.  There are schools-of-thought that the result of the aggregate function would be a Null value since at least one value is a null value.  Perhaps from a purist point-of-view, but not particularly useful for business reporting or many common SQL querying examples.

So how to avoid this error?

Alternative 1:
Simply add the statement 'SET ANSI_WARNINGS OFF' before your script.  As you might expect, this suppresses any of the ANSI-specified warnings such as the handling of null values in aggregate functions.   In the following sample code, the ANSI_WARNINGS is turned off, the same query is ran.   No warning appears on the Messages screen.  In this sample ANSI_WARNINGS is turned back so the rest of the script can be demonstrated.  But it is not strictly required to set ANSI_WARNINGS back on.   Setting it to Off will only last through that query session.

--Alternative 1: turn warnings off, rerun
SET ANSI_WARNINGS OFF
SELECT COUNT(*) AS CountOfRows, COUNT(value) AS CountOfValues, SUM(value) AS SumOfValues FROM @tst

--turn warnings back on, for this session
SET ANSI_WARNINGS ON


Disadvantages I have found so far.  From a testability view, this suppression of warning for the remainder of the query and session could suppress other legitimate warnings.  The only practical consequence I have seen is that if the query is designed with a graphical editor such as the Query Editor, the SET ANSI_WARNINGS statement will not be included in the edited query, and could be overwritten inadvertently in a copy-paste operation.

Alternative 2:
Rewrite the query to make explicit the handling of Null values.  In the rewritten version, the query won't rely on the Database Management Systems' handling of Nulls or the ANSI standard, the handling will be explicitly stated.   Basically, the Nullable column is converted to a nonnullable boolean column based on whether the original value was populated or not.  The new nonnullable boolean column (the bit data type in SQL Server) can be summed to meet the original requirement of a count of non-null values.   In the sample script, this is all done in a single statement.  If the query was the definition of an object such as a view, you would expect the column to have a not null constraint.

--Alternative 2: rewrite to provide a logical handling of the NULL value
SELECT COUNT(*) AS CountOfRows, SUM(CASE WHEN Value IS NOT NULL THEN 1 ELSE 0 END) AS CountOfValues, SUM(COALESCE(value,0)) AS SumOfValues FROM @tst



Disadvantages seem to be adjusting to the idea of using the SUM() aggregate function to produce what one might naturally write using the COUNT() aggregate function.  It is supported, but less readable in a graphically query designer.

Conclusion:
In most cases, writing a query "Warning: Null value is eliminated by an aggregate or other SET operation" should barely register with you.  At best, it might prompt you to verify the null-ability of the columns which you are querying matches your expectation.  However, if the query is to be used in the Source Adapter of a SQL Server Integration Services package, action must be taken. 

If it is a quick work-around that is needed, and there is a strong protection against the inadvertent modification of a query, you might consider adding that statement 'SET ANSI_WARNINGS OFF' before the beginning of the query. 

If a more resilient situation is called for, for example if the query is to be accessed from multiple callers in the form of a database view, you may consider doing the work of rewriting the query to explicitly handle null values.

Entire Script:
DECLARE @tst TABLE
(
VALUE int
)

INSERT INTO @tst (Value) VALUES (1)
INSERT INTO @tst (Value) VALUES (7)
INSERT INTO @tst (Value) VALUES (NULL)
INSERT INTO @tst (Value) VALUES (0)

SELECT * FROM @tst

--works but triggers the 'Warning: Null value is eliminated by an aggregate or other SET operation' warning
--SELECT COUNT(*) AS CountOfRows, COUNT(value) AS CountOfValues, SUM(value) AS SumOfValues FROM @tst

--Alternative 1: turn warnings off, rerun
SET ANSI_WARNINGS OFF
SELECT COUNT(*) AS CountOfRows, COUNT(value) AS CountOfValues, SUM(value) AS SumOfValues FROM @tst

--turn warnings back on, for this session
SET ANSI_WARNINGS ON

--Alternative 2: rewrite to provide a logical handling of the NULL value
SELECT COUNT(*) AS CountOfRows, SUM(CASE WHEN Value IS NOT NULL THEN 1 ELSE 0 END) AS CountOfValues, SUM(COALESCE(value,0)) AS SumOfValues FROM @tst