Once again, file this one under “Probably won’t matter as much after we get into 9.x features”. In the meantime, this bit of trickiness can improve performance when using extracts.
While I couldn’t attend Pawel Terlecki’s presentation “Speedier Queries with the Tableau Query Cache” last week, one of the ideas really stuck with me.
By adding all columns (measures and dimensions) in your extract to the Level of Detail of a blank sheet and then filtering the viz to return a single row, you can force all columns of the extract to be loaded into RAM (even if you don’t need them).
Note that this isn’t Tableau caching warming per-se, it’s simply getting data on your disk into RAM early so that it can be accessed by Tableau more quickly when the time comes.
Tableau normally doesn’t want to do this, by the way – our goals is to let customers analyze as much data as they want regardless of how much RAM is on their box. We purposefully don’t load data until it is needed.
However, there are times when forcing this behavior could be a good thing, assuming you have enough RAM.
Here’s a simple example:
- Using a 50M row Super Store extract (~ 1.2 GB, 25+ columns), I created a simple viz
- Said viz used 1 measure and 4 dimensions out of the 25+ columns in the extract
- I also created a “Load All Columns” (LOC) worksheet where ALL columns in the extract were added to Level of Detail and filtered by Order ID so that a single row was returned
- I then ran several tests using Performance Recorder to see how quickly my viz loaded based on whether or not I first touched the LOC sheet before running the viz
- Between each test I bounced my machine to clear my RAM out entirely
I saw a 25%+ increase in performance by running the LOC sheet before hitting the real viz. The same viz ran about 1 second faster if the extract was already pre-loaded in RAM:
You should be able to take this behavior and apply it to Server, which is where the fun really starts.
You’d run an “LOC” viz on the server now and then to make sure the extract is loaded into RAM. Then, any other report which utilizes the same data source would benefit from having it already resident in RAM when the time came to do work.
I suspect you really wouldn’t have to load ALL your columns in the LOC viz, either – only the columns which “cover” the fields used by the viz that you want to accelerate.
Someone try this and report back what you find? I bet you’ll see more of a difference when your extract is larger and/or the viz you execute uses more fields than the 5 in my little test.
Want to play with our demos? Please do:
Here’s what they do:
- Launchers: Various ways to launch vizzes. Pretty straight forward.
- Refreshers: Two mechanisms to automatically refresh vizzes - using a simple timer against a single viz, or multiple timers against multiple (duplicate) vizzes that refresh in a cadence and flip back and forth to create a more seamless transition (no spinners, no grey glass during refresh)
- Story Telling: Clippy! Clippy-as-avatar and guide. Make sure to click on a city OTHER than Adventure games to see him correct you.
- Responsive Tableau Vizzes: (Great on an iPad). Change the size of your browser and watch how a single viz refactors itself based on how much real estate is available
- Tables in the East: The Tableau Game: Mario-like console game where you try and make “Tables” a profitable category while driving behavior in a Tableau viz
- TabChat: You’ll need two for this collaboration demo. Get a buddy to login with you and start selecting marks, changing filters, etc. Choose which changes your friend made to apply to “your” viz
And where is the source code? It’s here:
https://github.com/Kovner/TITETG // Tableau Game
https://github.com/Kovner/tabChat //Tableau Chat
https://github.com/russch/YouDidWhat2014 // Russell’s 6 examples
#Tableau PM Neelesh Kamkolkar shows you how to load test Tableau Server with LoadRunner @hploadrunner
Short answer: Yes. Move along if you don’t care to sweat the details.
Many, moons ago I posted this nugget and a couple months ago I saw an interesting thread that wondered out loud if the fact that we now do client-side rendering changes this rule of thumb. A lot of folks now take it for granted.
Good news, it doesn’t. Even when doing client-side rendering in the browser, the lion’s share of the heavy lifting happens on the Server. Querying of the data source and creating the presentation model are server based. The browser simply draws things at the correct X/Y coordinates based the model which was created and lives in-session on the server. Those models can be re-used, and are more likely to be re-used if of a fixed size.
So keep setting exact height and width, campers.
Whoops! You created a viz with a custom font, installed that custom font on Tableau Server, but Server is rendering the viz with a generic parent font replacement - not your wonderful update to Comic Sans.
Why? One of these two reasons is correct. You figure out which:
- Tableau Server knows that the font that you chose is really, really ugly and we simply refuse to render it in order to spare you from embarrassment in front of the whole world. We look out for our customers like that.
- Tableau Server generally defaults to client-side rendering these days. So unless you force server-side rendering, it doesn’t matter that the font is installed on the Tableau Server box — your browser will go hunting locally for that font, and it probably doesn’t exist on your machine. To force server side rendering, use ?:render=false on your request for the viz. More info here: http://onlinehelp.tableausoftware.com/v8.1/server/en-us/browser_rendering.htm
When Tableau Server 8.2 releases, you’ll have the pleasure of a new API to work with. I’m sure there will be lots of chatter about the things you can do with the thing, so I’m not going to cover that here. The story I want to tell is a little different.
Over the weekend, evil Darth <redacted> created a guide that one can use to get a get a quick feel for how the API works without having to write lots of code to get there.
It is a combination of Tableau’s great help files on the API and a tool called Postman.
Lord <redacted> grudgingly gave his permission for me to share it with the little people.
You can download the guide here:
Of course, you’ll have to wait for 8.2 to release to use it. Sith’s revenge.
As always, this stuff is not supported by Tableau, you use the guidance at your own risk, and it may or may not be updated in the future.
The document has only been lightly proofed, so if you find errors, feel free to post them here. In between slaying Jedi, the author may have time to apply corrections.
Here’s some quick Google engine fodder. I suspect no one will ever need this because it is the result of me being the laziest coder on the face of the planet. (Yes, I’m proud).
I generally don’t. I’ve just used http: to refer to the viz and then rely on Tableau to redirect my request to https / 443
During the course of my career, this has saved me at least 15 keystrokes.
The “fix” is simple. Refer to the viz and the js file with https: like you should be doing in the first place.
@highvizability wrote a great piece last year about how to geocode a user’s address using R. You can read the article here and download a great sample workbook:
Let’s do the same thing but with someone’s IP address, shall we?
Tableau has already documented one method to approach this, but technology moves on. FYI, I wouldn’t use the following technique if I’m going to plot thousands of marks / ip addresses on a map - it would probably take too long. That said…
First, I found another great blog by a gentleman who figured out how to make ip-based geocoding go in R. You can read article here. Everything I did is based on his work.
Essentially, I’ve dumbed-down what Andrew put together and modified his function so that it only returns the latitude and longitude of the ip address being encoded:
if (1 == length(ip))
# a single IP address
url <- paste(c(“http://freegeoip.net/json/”, ip), collapse=”)
ret <- fromJSON(readLines(url, warn=FALSE))
ret <- data.frame(t(unlist(ret)))
latlon <- paste(ret$latitude,ret$longitude,sep=”,”)
The function above requires the rjson package, which lives in CRAN.
The function must also be available to your RServ server. This is generally accomplished by finding the Rserv.config file for RServ and adding a reference to a file which holds the text for your function.
For example, I dropped the text above into a file called geo.txt, and then plugged that value into the config file like so:
After that, all the work happens in Tableau,
You’ll create an expression which calls the function and passes it the ip address (in this case, named [ip] in my dataset):
Then, create two additional expressions which parse out the latitude and longitude:
…and you’re done!
You can download samples from here: http://1drv.ms/PUO69Q