Netgear GS108T VLANs

When you reset the 108T, the system creates three default VLANs.

This isn’t some kind of industry standard – it’s a netgear non-feature, and we have to live with it. So going forward, I’m not going to make any vlans for 2 and 3. We may end up using these for voip, anyway. There’s a lot to be said for built-in features that are supported, and so far, my experience with netgear voip support has been okay.
Continue reading Netgear GS108T VLANs

Make Meme/LOLCats Text with the GIMP

This tutorial explains how to make the “LOLCats” or “Meme” font so popular with the kids today. You can see a lot of these on the 4Chan /b/ channel, but don’t go there if you have any illusions that our society isn’t full of degenerates. The meme font is Impact Condensed, but to get the right “look”, you need to create a black outline around the regular font letters.

A couple tutorials explain how do to this with Photoshop. This tutorial explains how to do it with the free GIMP program.

From the windows menu, open up the Layers and the Paths windows. You may not be familiar with Paths, but it’s key to this task.

Select the text tool (the A icon), and then drag out a box. Type in your text. Set the font to Impact Condensed (on some systems, the meme font is simply called “Impact”), and a large pixel size, like 40 pixels. Set the color to white.

Then, click the “Paths from Text” button, which is down in the lower part of the Toolbox. This creates a new path in the Paths window.

Press the “D” key. This will set the colors back to black foreground / white background.

Then, click the “Paint along the Path” button in the Paths window. This is the weird looking brush icon next to the trash icon in the lower right. The “Stroke Path” dialog will appear.

Select “Stroke Line,” and set the path size to around 3 pixels. Select “Solid color.” Then click the “Stroke” button.

If the stroke steals too many pixels from the text, you might want to undo a few steps, duplicate the text layer, then re-do the path and stroke it. The duplicated text layer can be placed on top of the outlined text. That’s what was done on the example above.

There you go!

RAID 5 Parity. What is it, and how does it work?

One morning, I started wondering how RAID 5 parity works to rebuild a disk array. It seemed “magical” to me, that you can get redundancy and still use most of your disk capacity. So I searched for it… and turned up not very much info, and one other person’s unanswered question. A few articles explained it, but in a little more detail about performance, and less detail about the actual parity function. So I wrote this. The good articles were at:
Continue reading RAID 5 Parity. What is it, and how does it work?

Help Speed Up a MySQL Query by Helping the Optimizer

Here’s a noob-to-noob optimization trick. Suppose you have a database table with, say, 200,000 records, and you regularly select on multiple criteria. The rule for selection is to put the most specific WHERE clause first, and the least specific last. The goal is to cut down the search set to something small, and then search through the smaller set. Get all the queries using this order, then create a composite index over the keys to speed up the search even more.

Here are some before and after shots, based on real queries (from sf-active):

select * from tb where display='t' and parent_id=0 and id > 198000 limit 0,30

After:

select * from tb where id > 198000 and parent_id=0 and display='t' limit 0,30

This revision will now cause the first clause to eliminate most of the rows from the table, leaving only around 2,000 rows to scan. The second clause, parent_id, eliminates 50% of the remainder. Display=’t’ is the least selective clause.

Also, it wasn’t noted, but there are already indexes for display and parent_id. So we aren’t starting with absolutely nothing.

select * from tb where display='t' and parent_id=0 limit 0,30

After:

select * from tb where parent_id=0 and display='t' limit 0,30

Also do this:

alter table tb add index (parent_id, display)

That looks virtually identical. Again, this is a real-world situation, where the query was built-up dynamically. The optimization here is that I created an index that will speed up the select. The index matches the order of the query, so the query optimizer will be able to find the optimization easily.

Additionally, it would be a good thing to put all the clauses in all the queries into this order, from most specific to least specific, to gain the maximum optimization. I suspect the query optimizer already does this automatically, but, being meticulous about this seems like good mental discipline.

The real-world effect of this simple optimization, which took around two hours to complete, was dramatic. The slow query had been bogging down the server, with queries taking thousands of seconds to execute (or in our situation, to time-out, and require the admin to go in and kill the thread). Now, the query barely shows up in the process list, and the real-world speed feels like it takes less than five seconds to execute through the web (meaning, it includes dns lookup, tcp connection, and page rendering). Typically, it takes one second, and feels pretty fast.

See Also

Optimizing MySQL – Database Journal
MySQL Optimization – DevShed
Query Optimization

Paginating Database Results

I describe how others page over results, and how I do it.

I find fascinating URIs that looks like this:

http://mysite.com/index.php?page=3&search=foo

Why do programmers use a “page”? It seems odd, because that number is going to be translated to a starting record number, and a number of records (per page). Effectively, the URL could be this:

http://mysite.com/index.php?offset=30&pagesize=10

Now, you can show any arbitrary number of rows, starting at any arbitrary point in the results. Of course, what you lose are the “pages”, because you can get at any single record in the result. (If they can type a url, that is.) To regain the page-y-ness of the interface, you need to write a loop that constructs the pager navigation. One way is this:

for( $i=0; $i < $resultcount; $i+=$pagesize )
{
    // start the link
    print '<a href="/drupal/script.php';
    print "?offset=".$i."&pagesize='.$pagesize;
    print '">'.title.'</a>';
    // and close the link
}

This way reduces the coupling between the creation of the page navigation from the display of the results. It also creates a cleaner mapping to the SQL OFFSET statement.

If you need to know what page you’re on, just divide the offset by the page size.