A blend of programming and seo

Posts from — March 2009

5 cool things you can do with windows and php

Many PHP examples out there are designed for a linux/unix operating system. I am going to give some examples of some interesting functionality that only works with php running in a windows environment (IIS or apache).

1) Eject the CD-ROM

//create an instance of Windows Media Player
$mp = new COM("WMPlayer.OCX");
//ejects the first cd-rom on the drive list
$mp->cdromcollection->item(0)->eject();

2) Read and write from/to the registry

function registry_read($folder, $key)
{
    $WshShell = new COM("WScript.Shell");
   
    $registry =  "HKEY_LOCAL_MACHINE\SOFTWARE\\" . $folder . "\\"  . $key;
    $result = $WshShell->RegRead($registry);
   
    return($result);
}

$key = registry_read("RegisteredApplications","Firefox");

parameters:

  • Folder name – (key path past HKEY_LOCAL_MACHINE\SOFTWARE\\)
  • key – the key name to read from
function registry_write($folder, $key, $value,$type="REG_SZ")
{
    $WshShell = new COM("WScript.Shell");
   
    $registry =  "HKEY_LOCAL_MACHINE\SOFTWARE\\" . $folder . "\\"  . $key;
    $result = $WshShell->RegRead($registry);
    $result = $WshShell->RegWrite($registry,$value, $type);
     
    return($result);
}

parameters:

  • Folder name – (key path past HKEY_LOCAL_MACHINE\SOFTWARE\\)
  • key – the key name to write to
  • value – value that will be written to the key
  • type – key type (default: REG_SZ)

3) register and un-register phpscripts as a windows service

# registering a service

win32_create_service(array(
’service’ => ‘myservice’, # the name of your service
‘display’ => ’sample dummy PHP service’, # description
‘params’ => ‘c:\path\to\script.php run’, # path to the script and parameters
));

# un-registering a service

win32_delete_service(’myservice’);

# code run as a service

if ($argv[1] == 'run') {
  win32_start_service_ctrl_dispatcher('myservice');

  while (WIN32_SERVICE_CONTROL_STOP != win32_get_last_control_message()) {
    # write script here
    # as a general rule, keep it below 30 seconds through each loop iteration
  }
}

This uses the windows API Service DLL, which is not enabled by default. Here is how to install it:

  • Download the main library (it’s included in the main PECL extension download from php.net)
  • extract php_win32service.dll to your ext directory (where your php extension .dlls are located)
  • add the following line to your php.ini: extension=php_win32service.dll

4) print pages/data

#this is an example function that will format a host/printer name, for printing to shared printers over the network

function getPrinter($host,$SharedPrinterName) {
return “\\\\”.$host.”\\”.$SharedPrinterName;
}

#this opens the printer
$handle = printer_open(getPrinter(”my computer 2″,”my printer”));

An extensive list of functions for printing can be found here

#this is possible in *nix as well. Here is some example code

function lpr($string,$printer) {
$prn=(isset($printer) && strlen($printer))?”$printer”:C_DEFAULTPRN ;
$CMDLINE=”lpr -P $printer “;
$pipe=popen(”$CMDLINE” , ‘w’ );
if (!$pipe) {print “pipe failed.”; return “”; }
fputs($pipe,$string);
pclose($pipe);
}

This uses the windows API Service DLL, which is not enabled by default. Here is how to install it:

  • Download the main library (it’s included in the main PECL extension download from php.net)
  • extract php_printer.dll to your ext directory (where your php extension .dlls are located)
  • add the following line to your php.ini: extension=php_printer.dll

5) List the current system processes

# list all the current processes running on the system

print_r(win32_ps_list_procs());

other related commands:

# Retrieves statistics about the global memory utilization
print_r(win32_ps_stat_mem());

# Retrieves statistics about the process with the process id pid (if no process id is given, the current process will be used)
print_r(win32_ps_stat_proc(int processid));

This uses the windows API Service DLL, which is not enabled by default. Here is how to install it:

  • Download the main library (it’s included in the main PECL extension download from php.net)
  • extract php_win32ps.dll to your ext directory (where your php extension .dlls are located)
  • add the following line to your php.ini: extension=php_win32ps.dll

March 31, 2009   14 Comments

5 ways to optimize mysql inserts

The following are five ways to improve queries involving table inserts:

1) use LOAD DATA INFILE when loading data from a text file

This is around 20 times faster than using insert statements.

2) use INSERT statements with multiple VALUES lists to insert several rows at a time

This is many times faster than using separate single-row insert statements. Tuning the bulk_insert_buffer_size variable can also make inserts (to tables that contain rows) even faster.

3) enable concurrent inserts for myisam tables

The concurrent_insert system variable can be set to modify the concurrent-insert processing. By default, the variable is set to 1. If concurrent_inserts is set to 0, concurrent inserts are disabled. If the variable is set to 2, concurrent inserts at the end of the table are allowed even for tables that have deleted rows.

4) use insert delayed

This is useful if you have clients that cannot or need not wait for the insert to complete. This is a common situation when you use MySQL for logging and you also periodically run select and update statements that take a long time to complete. When a client uses insert delayed, the server returns right away, and the row is queued to be inserted when the table is not in use by any other thread. Another benefit of using insert delayed is that inserts from many clients are bundled together and written in one block. This is much faster than performing many separate inserts.

5) lock your tables before inserting (for non-transactional tables)

This benefits performance because the index buffer is flushed to disk only once, after all insert statements have completed. Normally, there would be as many index buffer flushes as there are insert statements. Explicit locking statements are not needed if you can insert all rows with a single insert.

To obtain faster insertions for transactional tables, you should use start transaction and commit instead of lock tables.

March 30, 2009   5 Comments

10 tips for optimizing mysql queries

  • 1) use the explain command
    Use multiple-row INSERT statements to store many rows with one SQL statement.

    The explain command can tell you which indexes are used with the specified query and many other pieces of useful information that can help you choose a better index or query.

    Example of usage: explain select * from table

    explanation of row output:

    • table—The name of the table.
    • type—The join type, of which there are several.
    • possible_keys—This column indicates which indexes MySQL could use to find the rows in this table. If the result is NULL, no indexes would help with this query. You should then take a look at your table structure and see whether there are any indexes that you could create that would increase the performance of this query.
    • key—The key actually used in this query, or NULL if no index was used.
    • key_len—The length of the key used, if any.
    • ref—Any columns used with the key to retrieve a result.
    • rows—The number of rows MySQL must examine to execute the query.
    • extra—Additional information regarding how MySQL will execute the query. There are several options, such as Using index (an index was used) and Where (a WHERE clause was used).
  • 2) use less complex permissions
  • The more complex your permissions setup, the more overhead you have. Using simpler permissions when you issue GRANT statements enables MySQL to reduce permission-checking overhead when clients execute statements.

  • 3) specific mysql functions can be tested using the built-in “benchmark” command

    If your problem is with a specific MySQL expression or function, you can perform a timing test by invoking the BENCHMARK() function using the mysql client program. Its syntax is BENCHMARK(loop_count,expression). The return value is always zero, but mysql prints a line displaying approximately how long the statement took to execute

  • 4) optimize where clauses
    • Remove unnecessary parentheses
    • COUNT(*) on a single table without a WHERE is retrieved directly from the table information for MyISAM and MEMORY tables. This is also done for any NOT NULL expression when used with only one table.
    • If you use the SQL_SMALL_RESULT option, MySQL uses an in-memory temporary table
  • 5) Run optimize table
  • This command defragments a table after you have deleted a lot of rows from it.

  • 6) avoid variable-length column types when necessary
  • For MyISAM tables that change frequently, you should try to avoid all variable-length columns (VARCHAR, BLOB, and TEXT). The table uses dynamic row format if it includes even a single variable-length column.

  • 7) insert delayed
  • Use insert delayed when you do not need to know when your data is written. This reduces the overall insertion impact because many rows can be written with a single disk write.

  • 8 ) use statement priorities
    • Use INSERT LOW_PRIORITY when you want to give SELECT statements higher priority than your inserts.
    • Use SELECT HIGH_PRIORITY to get retrievals that jump the queue. That is, the SELECT is executed even if there is another client waiting.
  • 9) use multiple-row inserts
  • Use multiple-row INSERT statements to store many rows with one SQL statement.

  • 10) synchronize data-types
  • Columns with identical information in different tables should be declared to have identical data types so that joins based on the corresponding columns will be faster.

    March 27, 2009   3 Comments

    The most powerful mysql command

    The most powerful command within mysql is explain. Explain can tell you exactly what mysql is doing when you execute a query and with this information, you can find slow queries and minimize execution time, which can significantly improve the speed of your web application.

    How to use the explain command

    Here is a simple example of its usage:

    explain statement1 The most powerful mysql command

    Database Schema:

    (users table)

    users schema The most powerful mysql command

    (address table)

    address schema The most powerful mysql command

    In this simple example, I am selecting a record that is representing a user, based on a userid.

    Here is the output:

    Variable Details
    explain id The most powerful mysql command The ID of this table in the query. EXPLAIN will create one output record for each table in the query.
    explain select type The most powerful mysql command possible values: SIMPLE, PRIMARY, UNION, DEPENDENT UNION, SUBSELECT, and DERIVED.
    explain table The most powerful mysql command The name of the table MYSQL will read the records from.
    explain type The most powerful mysql command The type of join that mysql will use. Possible values: eq_ref,ref,range, index, or all.
    explain possible keys The most powerful mysql command a list of indexes (or NULL if none) mysql can use to find rows in the table.
    explain key The most powerful mysql command The name of the index MYSQL will use (after checking all possible indexes).
    explain key len The most powerful mysql command The size of the key in bytes.
    explain ref The most powerful mysql command The columns or values that are used to match against the key
    explain rows The most powerful mysql command The number of rows mysql thinks it needs to examine to execute the query.
    explain extra The most powerful mysql command extra information about the query

    This example is pretty straight forward. Since we are peforming a search based on the primary key (userid), there can be only one record that can possible match (the rows variable is 1).

    A more advanced example:

    statement adv The most powerful mysql command

    This query is more advanced than the first one. It is performing an inner join on the users and address table based on the userid. The userid is a primary key within the users table, but it is not an index in the address table. The output of the explain command shows us the following:

    (users table)

    Type: const
    Possible_Keys: primary
    Ref: const

    (address table)

    Type: all
    Possible_Keys: (none)
    Ref: (none)

    The first table is optimized. It is using the primary key for this query. The second table, however is not optimized. The type is all and the Possible_keys=(none), which means it is going to have to go through a full table-scan. Adding an index on the user field optimizes this query.

    Final output after index is added:

    (users table)

    Type: const
    Possible_Keys: primary
    Ref: const

    (address table)

    Type: const
    Possible_Keys: primary
    Ref: const

    More information on this command can be found Here

    March 26, 2009   3 Comments

    How to find slow mysql queries

    It has happened to all of us running a website or application using mysql as its back-end database. Performance is suddenly very sluggish and you have no idea what is causing it. Now there may be other factors that are causing the issue (overloaded CPU, harddrive running out of space, or a lack of bandwidth), but it could also be a query that is not optimized and/or is taking much longer than it should to return.

    How do you know which queries are taking the longest to execute? Mysql has built-in functionality for checking this through the slow query log.

    To enable (do one of the following):

    1) add this to /etc/my.cnf

    log-slow-queries=/tmp/slow_queries.log
    long_query_time=10

    2) call mysqld with –log-slow-queries[=/tmp/slow_queries.log]

    long_query_time is the maximum amount of seconds a query can take before it will be logged to the slow query log.

    other related options:

    –log-slow-admin-statements

    Log slow administrative statements such as OPTIMIZE TABLE, ANALYZE TABLE, and ALTER TABLE to the slow query log.

    –log-queries-not-using-indexes

    If you are using this option with –log-slow-queries, queries that do not use indexes are logged to the slow query log.

    mysql info How to find slow mysql queries

    If slow query logging has been enabled successfully, you will see “ON” in the VALUE field for “log_slow_queries” (shown above).

    Note: Queries handled by the query cache are not added to the slow query log, nor are queries that would not benefit from the presence of an index because the table has zero rows or one row.

    You may also run into the case where a query is slow at one time (such as when you are logging it) but not another (if you execute it manually):

    • A table may be locked, causing the query to wait. the lock_time indicates how long the query waited for locks to be released
    • none of the data or indexes have been cached in memory. This is common when MySQL first starts or your tables have not been optimizied
    • a background process was running, making disk I/O considerably slower
    • The server may have been overloaded with other unrelated queries at the same time, and there wasn’t enough CPU power to do the job efficiently

    Log analysis

    MySQL also comes with mysqldumpslow, a perl script that can summarize the slow query log and provide a better idea of how often each slow query executes.

    March 25, 2009   No Comments