A cou­ple of weeks ear­lier, Ama­zon announced sup­port for Local Sec­ondary Indexes (LSI) for DynamoDB. You can now per­form fast, effi­cient queries against DynamoDB tables using attrib­utes that are not part of the exist­ing Hash and Range key model with­out resort­ing to the use of scans.

As a result to the new fea­ture the DynamoDB query API has also gone through some changes, as did the AWSSDK for .Net. From ver­sion 1.5.18.0 onwards, there’s a new top level name­space Amazon.DynamoDBv2 which con­tains a mir­ror set of types to those under the orig­i­nal Amazon.DynamoDB name­space, albeit with minor changes to sup­port the new LSI feature.

Query syn­tax change

Due to the changes in the under­ly­ing AWSSDK, I have decided to make some changes to the query syn­tax sup­ported by DynamoDB.SQL too – namely, to remove the need for the spe­cial key­words @HashKey and @RangeKey and instead allow you to use the attrib­utes names for your hash and range keys.

For exam­ple, given a table like the one out­lined in the DynamoDB docs:

image

To write a query to find all sub­jects start­ing with “a” in the “S3” forum, you would pre­vi­ously write:

SELECT * FROM Thread WHERE @HashKey = \”S3\” AND @RangeKey BEGINS WITH \”a\”

In the new ver­sion of DynamoDB.SQL, you would write the fol­low­ing instead:

SELECT * FROM Thread WHERE Forum­Name = \”S3\” AND Sub­ject BEGINS WITH \”a\”

This syn­tax change only applies to the exten­sion meth­ods for the Ama­zon­Dy­namoD­B­Client and DynamoD­B­Con­text types under the new Amazon.DynamoDBv2 name­space. The exten­sion meth­ods them­selves are only avail­able under a new name­space DynamoDbV2.SQL.Execution in the DynamoDb.SQL.dll.

The syn­tax for scans on the other hand, has remained the same in both the new and the old API.

Local Sec­ondary Index support

You can spec­ify that a query should use a Local Sec­ondary Index (LSI) by using the Index option in the WITH clause.

For exam­ple, given a Thread table and an index Last­PostIn­dex, as out­lined in the DynamoDB docs:

image

To find all the posts in the “S3” forum since the 1st May 2013, you can write the query as following:

SELECT * FROM Thread WHERE Forum­Name = \”S3\” AND Last­Post­Date­Time >= \”2013–05-01\”

WITH (Index(LastPostIndex, true))

The WITH clause is where you spec­ify optional query para­me­ters, such as NoCon­sis­ten­tRead, and Page­Size. (please refer to the Get­ting Started guide on avail­able query parameters).

The Index option allows you to spec­ify the name of the index, in this case that’s “Last­PostIn­dex”, and a boolean flag to spec­ify whether or not all attrib­utes should be returned.

For the above query, because we’re ask­ing for all attrib­utes to be sent back with *, and that attrib­utes such as Replies are not pro­jected into the index, they will be fetched (auto­mat­i­cally per­formed by DynamoDB) from the main table at addi­tional con­sumed capac­ity units.

 

On the other hand, if you want only the pro­jected attrib­utes back from the index, we can tweak the query slightly:

SELECT * FROM Thread WHERE Forum­Name = \”S3\” AND Last­Post­Date­Time >= \”2013–05-01\”

WITH (Index(LastPostIndex, false))

In which case, only Forum­Name, Last­Post­Date­Time and Sub­ject will be returned by the query.

 

Finally, if you are inter­ested in a spe­cific set of attrib­utes, you can also spec­ify them in the SELECT clause:

SELECT Forum­Name, Sub­ject FROM Thread

WHERE Forum­Name = \”S3\” AND Last­Post­Date­Time >= \“2013–05-01\”

WITH     (Index(LastPostIndex, false))

 

Some ref­er­ence links:

AWS announces Local Sec­ondary Index sup­port for DynamoDB

DynamoDB docs on Local Sec­ondary Indexes

DynamoDB docs on Query

Query­ing with an Index attribute in DynamoDB.SQL

Get­ting started with DynamoDB.SQL

Share

.Net 4 intro­duced the Lazy<T> type which allows you to cre­ate an object that can be lazily ini­tial­ized so that you can delay the cre­ation of large objects, for instance.

How­ever, if your ini­tial­iza­tion logic has the poten­tial to except at run­time (e.g. time out excep­tions read­ing from some exter­nal data source) then you should pay close atten­tion to which con­struc­tor you use to cre­ate a new instance of the Lazy<T> type. Depend­ing on the selected LazyThread­Safe­t­y­Mode, excep­tions in the ini­tial­iza­tion code might be cached and rethrown on all sub­se­quent attempts to fetch the lazily ini­tial­ized value. Whilst this ensures that threads will always get the same result, hence remov­ing ambi­gu­ity, it does mean that you’ve got only one shot at ini­tial­iz­ing that value…

 

LazyThread­Safe­t­y­Mode

In cases where you need to be able to tol­er­ate occa­sional ini­tial­iza­tion errors (e.g. read­ing a large object from S3 can fail from time to time for a num­ber of rea­sons) and be able to try again at a sec­ond attempt, the rule of thumb is to instan­ti­ate the Lazy<T> type by set­ting LazyThread­Safe­t­y­Mode to Pub­li­ca­tionOnly. In Pub­li­ca­tionOnly thread safety mode, mul­ti­ple threads can invoke the ini­tial­iza­tion logic but the first thread to com­plete the ini­tial­iza­tion suc­cess­fully sets the value of the Lazy<T> instance.

For exam­ple, the fol­low­ing only works under the Pub­li­ca­tionOnly mode:

 

F#

F# pro­vides a slightly nicer syn­tax for defin­ing a lazy com­pu­ta­tion:

image

the Control.Lazy<T> type is an abbre­vi­a­tion of the BCL Lazy<T> type with a Force exten­sion method which under the hood just calls Lazy<T>.Value.

Pre­sum­ably the above trans­lates roughly to the fol­low­ing C# code:

var x = 10;

var result = new Lazy<int>(() => x + 10);

and the thread safety mode using the Lazy(Func<T>) con­struc­tor is LazyThreadSafetyMode.ExecutionAndPublication which caches and rethrows any excep­tions caught in the ini­tial­iza­tion. E.g.:

image

Share

After a long Easter hol­i­day filled with late night cod­ing ses­sions I find myself wide awake at 2am… good job I’ve still got my plu­ral­sight sub­scrip­tion and a quick look at the Algo­rithms and Data Struc­tures course again at least gave me some­thing to do to relax the mind with some back-to-school style imple­men­ta­tion of com­mon sort­ing algo­rithms in F#:

Whilst not the most per­for­mant imple­men­ta­tions I’m sure, I hope at least it goes to show how eas­ily and con­cisely these sim­ple algo­rithms can be expressed in F#! Now back to that sleep thing…

Share

I talked about the XML and JSON seri­al­iza­tion of F# types in a pre­vi­ous post, and since then F# 3.0 has been released and a new [CLIMutable] was qui­etly added amidst the hype sur­round­ing the awe­some type providers!

 

CLIMutable Attribute

When applied to a F# record type, the CLIMutable attribute tells the F# com­piler to gen­er­ate a default para­me­ter­less con­struc­tor as well as prop­erty get­ters and set­ters so that when work­ing with the record type from other .Net lan­guages it’ll appear as a pretty stan­dard, muta­ble CLI type that you’d expect.

How­ever, when work­ing in F#, the nor­mal rules as far as record types are con­cerned still apply – immutabil­ity by default, pat­tern match­ing, cloning using the with key­word, etc.

For a sim­ple record type Per­son, let’s have a look at the com­pile code with and with­out the CLIMutable attribute:

image image

With­out the CLIMutable attribute, this is how the record type is nor­mally compiled:

image

With the CLIMutable attribute applied, things look a lot different:

image

That’s all well and good, but why is this use­ful you might ask?

Because many seri­al­iz­ers, such as the BCL’s XmlSe­ri­al­izer (as well as other seri­al­iz­ers avail­able in the open source space) only work with types that has a default con­struc­tor and con­tains prop­erty setters.

 

XmlSe­ri­al­izer and Record types

Unlike the Dat­a­Con­tract­Se­ri­al­izer which only requires a type to be dec­o­rated with a Seri­al­iz­able or Dat­a­Con­tract attribute, the XmlSe­ri­al­izer on the other hand, also requires the type to define a para­me­ter­less constructor.

Whilst both seri­al­iz­ers gen­er­ate XML out­puts, Dat­a­Con­tract­Se­ri­al­izer is intended for mar­shalling data (that con­forms to a ‘con­tract’) for trans­porta­tion over the wire and there­fore less con­cerned with read­abil­ity of its out­put and offers lit­tle option for you to cus­tomize the gen­er­ated XML. It’s there­fore quite happy to spit out rather unread­able XML for our Per­son record type above:

 

<FSI_0004.Person xmlns=“http://schemas.datacontract.org/2004/07/”  xmlns:i=“http://www.w3.org/2001/XMLSchema-instance”><Age_x0040_>30</Age_x0040_><Name_x0040_>Yan Cui</Name_x0040_></FSI_0004.Person>

 

Mean­while, in the land of the XmlSe­ri­al­izer, its sole pur­pose of exis­tence is to gen­er­ate XML and offers a pla­toon of options to help ensure its out­put meets your func­tional and aes­thetic needs. By default it’ll gen­er­ate nice, indented out­put for our CLIMutable ver­sion of Per­son record type:

 

<?xml version=“1.0″?>

<Per­son xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance” xmlns:xsd=“http://www.w3.org/2001/XMLSchema”>

  <Name>Yan Cui</Name>

  <Age>30</Age>

</Person>

 

In addi­tion, you can cus­tomize the XML out­put using the nor­mal XML-related attributes:

image

<?xml version=“1.0″?>

<Per­son xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance” xmlns:xsd=“http://www.w3.org/2001/XMLSchema” PersonName=“Yan Cui”>

  <PersonAge>30</PersonAge>

</Person>

 

OSS Seri­al­iz­ers

Of the OSS JSON seri­al­iz­ers I bench­mark reg­u­larly, JSON.Net (v4.5.11 tested) works with both nor­mal and CLIMutable record types from F#. ServiceStack.Text (v3.9.37 tested) doesn’t work with ‘vanilla’ record types on dese­ri­al­iza­tion (fields are left with default val­ues), but you can workaround by mak­ing the fields muta­ble or add the CLIMutable attribute to the type.

 

I hope this proves to be use­ful to you, and if like us you have a lot of C# code hang­ing around just to get pretty XML out of your F# record types, dare I say it’s about to throw away those C# code! Winking smile

Share

Just a quick note to say that another minor update to DynamoDB.SQL has been release, you can view the release notes here.

 

The lat­est update adds sup­port for a TSQL style WITH key­word for spec­i­fy­ing optional para­me­ters for tweak­ing the query/scan oper­a­tion. For queries, you can spec­ify the NoCon­sis­ten­tRead and Page­Size options to use even­tu­ally con­sis­tent read and throt­tle the num­ber of items returned per request respec­tively. Sim­i­larly for scans, you can use the Page­Size option for throt­tling your scan requests too, but the DynamoDB scans does not sup­port strong con­sis­tency.

 

Accord­ing to DynamoDB best prac­tices, you should avoid sud­den bursts of read activ­ity, using the new Page­Size option you can make sure that your query/scan does not con­sume too many read capac­ity unit in a short burst and end up caus­ing more crit­i­cal reads to be throttled.

 

For exam­ple, a query which returns 10 items per request using even­tu­ally con­sis­tent read will look some­thing like this:

image

whereas a scan will look like:

image

For more details about the full syn­tax, please refer to the Get­ting Started doc­u­ment, which has been updated to include the new WITH key­word.

 

Enjoy!

Share