SQL Clone
SQLServerCentral is supported by Redgate
 
Log in  ::  Register  ::  Not logged in
 
 
 


Storing IPv4 Addresses for Performance


Storing IPv4 Addresses for Performance

Author
Message
Jean-Sebastien Carle
Jean-Sebastien Carle
Valued Member
Valued Member (59 reputation)Valued Member (59 reputation)Valued Member (59 reputation)Valued Member (59 reputation)Valued Member (59 reputation)Valued Member (59 reputation)Valued Member (59 reputation)Valued Member (59 reputation)

Group: General Forum Members
Points: 59 Visits: 81
Comments posted to this topic are about the item Storing IPv4 Addresses for Performance
nicholastjh
nicholastjh
Grasshopper
Grasshopper (14 reputation)Grasshopper (14 reputation)Grasshopper (14 reputation)Grasshopper (14 reputation)Grasshopper (14 reputation)Grasshopper (14 reputation)Grasshopper (14 reputation)Grasshopper (14 reputation)

Group: General Forum Members
Points: 14 Visits: 8
Nice article. Very informative.

But at the final function where 128 is subtracted from the result of ParseName, before being multiplied by 16777216 (2^24), could potentially yield negative results, if the first final octet is not above 128.

For example: 127.0.0.1 would result in -16777215.
loganmerazzi
loganmerazzi
Valued Member
Valued Member (63 reputation)Valued Member (63 reputation)Valued Member (63 reputation)Valued Member (63 reputation)Valued Member (63 reputation)Valued Member (63 reputation)Valued Member (63 reputation)Valued Member (63 reputation)

Group: General Forum Members
Points: 63 Visits: 222
1 question:
What if we create the solution using CLR? Is it possible? And what about the performance, since it's compiled?

Thanks!!!
HansVE
HansVE
Valued Member
Valued Member (74 reputation)Valued Member (74 reputation)Valued Member (74 reputation)Valued Member (74 reputation)Valued Member (74 reputation)Valued Member (74 reputation)Valued Member (74 reputation)Valued Member (74 reputation)

Group: General Forum Members
Points: 74 Visits: 339
I store these as four tinyint columns. Also uses just four bytes but is human-readable, does not require all your conversions, has implicit validation, and better meets the 1NF goal of atomicity.
nimdil
nimdil
SSC Journeyman
SSC Journeyman (96 reputation)SSC Journeyman (96 reputation)SSC Journeyman (96 reputation)SSC Journeyman (96 reputation)SSC Journeyman (96 reputation)SSC Journeyman (96 reputation)SSC Journeyman (96 reputation)SSC Journeyman (96 reputation)

Group: General Forum Members
Points: 96 Visits: 92
nicholastjh (8/19/2009)
Nice article. Very informative.

But at the final function where 128 is subtracted from the result of ParseName, before being multiplied by 16777216 (2^24), could potentially yield negative results, if the first final octet is not above 128.

For example: 127.0.0.1 would result in -16777215.

That's the whole point. Some IP addresses will map to negative integers. As there are 2^32 IP Addresses and 2^31 non-negative integers in SQL Server we have to use positive as well as negative values.

The idea with four columns - while not bad - has some flaws:
1. There is no merits with 1NF as IP address is a complete being. Would you store postal code with few char(1) columns?
2. If you want to perform table wide bit operation with mask (mask may be from 0 to 32 actually) you will have to either map four tinyints to one int the same way it is presented in the article or map it to bigint. Not good for performance :>

If you want readability - just use view with some ip_int_to_ip_string computed column.
lhowe
lhowe
Ten Centuries
Ten Centuries (1K reputation)Ten Centuries (1K reputation)Ten Centuries (1K reputation)Ten Centuries (1K reputation)Ten Centuries (1K reputation)Ten Centuries (1K reputation)Ten Centuries (1K reputation)Ten Centuries (1K reputation)

Group: General Forum Members
Points: 1047 Visits: 313
Darn it HansVE, you beat me to the punch! I was going to say exactly the same thing. I don't see why someone would go to all of the trouble to convert IPv4 values this way, and back again, when it's far easier just to store them as four tinyint values.
tdcheek
tdcheek
Grasshopper
Grasshopper (16 reputation)Grasshopper (16 reputation)Grasshopper (16 reputation)Grasshopper (16 reputation)Grasshopper (16 reputation)Grasshopper (16 reputation)Grasshopper (16 reputation)Grasshopper (16 reputation)

Group: General Forum Members
Points: 16 Visits: 10
I've always liked storing IP's as binary(4) - still 4 bytes, but simpler conversions:



DECLARE @IpBin binary(4)
DECLARE @IpString varchar(15)
SET @IpString = '101.202.33.44'

--convert string to binary
SET @IpBin = CONVERT(binary(1), CONVERT(tinyint, PARSENAME(@IpString, 4)))
+ CONVERT(binary(1), CONVERT(tinyint, PARSENAME(@IpString, 3)))
+ CONVERT(binary(1), CONVERT(tinyint, PARSENAME(@IpString, 2)))
+ CONVERT(binary(1), CONVERT(tinyint, PARSENAME(@IpString, 1)))

SELECT @IpBin

--convert binary to string
SELECT
CAST(CAST(SUBSTRING(@IpBin,1,1) AS tinyint) AS varchar(3)) + '.' +
CAST(CAST(SUBSTRING(@IpBin,2,1) AS tinyint) AS varchar(3)) + '.' +
CAST(CAST(SUBSTRING(@IpBin,3,1) AS tinyint) AS varchar(3)) + '.' +
CAST(CAST(SUBSTRING(@IpBin,4,1) AS tinyint) AS varchar(3))


HansVE
HansVE
Valued Member
Valued Member (74 reputation)Valued Member (74 reputation)Valued Member (74 reputation)Valued Member (74 reputation)Valued Member (74 reputation)Valued Member (74 reputation)Valued Member (74 reputation)Valued Member (74 reputation)

Group: General Forum Members
Points: 74 Visits: 339
nimdil (8/19/2009)
The idea with four columns - while not bad - has some flaws:
1. There is no merits with 1NF as IP address is a complete being. Would you store postal code with few char(1) columns?
2. If you want to perform table wide bit operation with mask (mask may be from 0 to 32 actually) you will have to either map four tinyints to one int the same way it is presented in the article or map it to bigint. Not good for performance :>

If you want readability - just use view with some ip_int_to_ip_string computed column.


1. You do not know of subnetting? Do you also store first and last names of people together in one column?

2. "Table wide bit operation" can be done using more than one column. Masks also are typically written by octet(s).

A "ip_int_to_ip_string computed column" will impede performance, as will the functions in the article.

The only "flaw" is that predicates, joins, etc. may need to use more than one column, and so more typing. The flaws with using integer are obvious from the need for such an article as this.
Elliott Whitlow
Elliott Whitlow
SSCoach
SSCoach (16K reputation)SSCoach (16K reputation)SSCoach (16K reputation)SSCoach (16K reputation)SSCoach (16K reputation)SSCoach (16K reputation)SSCoach (16K reputation)SSCoach (16K reputation)

Group: General Forum Members
Points: 16400 Visits: 5314
I have to admit the four tiniyints was my first idea but I realized the limitations imposed by that solution immediately, yes its human readable, so what, add the function to your select statement, problem solved.

I believe the binary(4) solution also has merit. I would be curious how it stacks up against the others, since it is just a cast operation and no math.

When the four octets are stored in a single field you are able to do IN operations or much cleaner (and I'm sure faster) correlated sub-queries.

I just see more options with a single column solution and will not be particularly worried about what NF it fits it. Human readability is not a major concern in the DB, if that was then we would never store ID values for a customer id, we would store all the customer information in the table with the order and I think we can agree that is NOT a good solution. Human readability can be achieved with minimal effort if necessary.

Also, as with any problem there is more than one solution, the four tinyints may be just fine for your app, but I know that the next time I need to store IP addresses this article will come to mind..

CEWII
Andrew in WV
Andrew in WV
SSC Veteran
SSC Veteran (291 reputation)SSC Veteran (291 reputation)SSC Veteran (291 reputation)SSC Veteran (291 reputation)SSC Veteran (291 reputation)SSC Veteran (291 reputation)SSC Veteran (291 reputation)SSC Veteran (291 reputation)

Group: General Forum Members
Points: 291 Visits: 1376
tdcheek (8/19/2009)
I've always liked storing IP's as binary(4) - still 4 bytes, but simpler conversions:


I like this format as well, since that's essentially what IP addresses are anyway. Like using INT and four separate TINYINT columns, it is efficient on space and has implicit validation. However, it has a few other advantages I like:

1) The queries I perform are very simple and efficient. Most of them are sargable. You don't have the problem of half the address space being negative that you have with INT. It is very easy to say:

WHERE @IPAddress BETWEEN RangeLowerLimit AND RangeUpperLimit





2) When viewed in a query window, it is represented as a hexadecimal sequence. That makes it just as easy to compare two addresses visually as the dotted notation.

3) It's relatively simple to convert to dotted notation if necessary.


Andrew

--Andrew
Go


Permissions

You can't post new topics.
You can't post topic replies.
You can't post new polls.
You can't post replies to polls.
You can't edit your own topics.
You can't delete your own topics.
You can't edit other topics.
You can't delete other topics.
You can't edit your own posts.
You can't edit other posts.
You can't delete your own posts.
You can't delete other posts.
You can't post events.
You can't edit your own events.
You can't edit other events.
You can't delete your own events.
You can't delete other events.
You can't send private messages.
You can't send emails.
You can read topics.
You can't vote in polls.
You can't upload attachments.
You can download attachments.
You can't post HTML code.
You can't edit HTML code.
You can't post IFCode.
You can't post JavaScript.
You can post emoticons.
You can't post or upload images.

Select a forum

































































































































































SQLServerCentral


Search