Archive | Developer RSS feed for this section

Web Technology – Application Events

Web application events
In  servlet 2.3 spec, web application events are introduced that give you greater degree of control over your web application. The two important application events are:

  1. Application startup and shutdown
  2. Session creation and invalidation

As their names suggest, application startup event occurs when your web application is first loaded and started by the Servlet container and application shutdown event occurs when the web application is shutdown.

Session creation event occurs every time a new session is created on the server and similarly session invalidation event occurs every time a session is invalidated. To make use of these web application events and to do something useful you’ll have to create and make use of special “listener” classes.

Listener
These are simple Java classes which implement one of the two following interfaces:

  1. javax.servlet.ServletContextListener
  2. javax.servlet.http.HttpSessionListener

If you want your class to listen for application startup and shutdown events then implement ServletContextListener interface. If you want your class to listen for session creation and invalidation events then implement HttpSessionListener interface.

ServletContextListener – This interface contains two methods :
[code]]czoxMTI6XCJwdWJsaWMgdm9pZCBjb250ZXh0SW5pdGlhbGl6ZWQoU2VydmxldENvbnRleHRFdmVudCBzY2UpOw0KcHVibGljIHZvaWR7WyYqJl19IGNvbnRleHREZXN0cm95ZWQoU2VydmxldENvbnRleHRFdmVudCBzY2UpO1wiO3tbJiomXX0=[[/code]

HttpSessionListener – This interface contains two methods also:
[code]]czoxMDA6XCJwdWJsaWMgdm9pZCBzZXNzaW9uQ3JlYXRlZChIdHRwU2Vzc2lvbkV2ZW50IHNlKTsNCnB1YmxpYyB2b2lkIHNlc3Npb257WyYqJl19RGVzdHJveWVkKEh0dHBTZXNzaW9uRXZlbnQgc2UpO1wiO3tbJiomXX0=[[/code]

Example of usage – use HttpSessionListener to count how many active session[code]]czo5MzpcIg0KaW1wb3J0IGphdmF4LnNlcnZsZXQuaHR0cC5IdHRwU2Vzc2lvbkxpc3RlbmVyOw0KaW1wb3J0IGphdmF4LnNlcnZsZXR7WyYqJl19Lmh0dHAuSHR0cFNlc3Npb25FdmVudDtcIjt7WyYqJl19[[/code][code]]czozNzA6XCJwdWJsaWMgY2xhc3MgU2Vzc2lvbkNvdW50ZXIgaW1wbGVtZW50cyBIdHRwU2Vzc2lvbkxpc3RlbmVyIHsNCnByaXZhdGV7WyYqJl19IHN0YXRpYyBpbnQgYWN0aXZlU2Vzc2lvbnMgPSAwOw0KLyogU2Vzc2lvbiBDcmVhdGlvbiBFdmVudCAqLw0Kw4LCoHB1YmxpYyB2b3tbJiomXX1pZCBzZXNzaW9uQ3JlYXRlZChIdHRwU2Vzc2lvbkV2ZW50IHNlKSB7DQrDgsKgIGFjdGl2ZVNlc3Npb25zKys7DQrDgsKgfQ0KLyoge1smKiZdfVNlc3Npb24gSW52YWxpZGF0aW9uIEV2ZW50ICovDQrDgsKgcHVibGljIHZvaWQgc2Vzc2lvbkRlc3Ryb3llZChIdHRwU2Vzc2lvbkV7WyYqJl19dmVudCBzZSkgew0Kw4LCoCBpZihhY3RpdmVTZXNzaW9ucyAmZ3Q7IDApDQrDgsKgIGFjdGl2ZVNlc3Npb25zLS07DQrDgsKgfVwiO3tbJiomXX0=[[/code][code]]czo3ODpcInB1YmxpYyBzdGF0aWMgaW50IGdldEFjdGl2ZVNlc3Npb25zKCkgew0Kw4LCoCByZXR1cm4gYWN0aXZlU2Vzc2lvbnM7DQp7WyYqJl19w4LCoH0NCn1cIjt7WyYqJl19[[/code]Register listener to the web application[code]]czo2NzA6XCINCiZsdDshLS0gV2ViLnhtbCAtLSZndDsNCiZsdDs/eG1sIHZlcnNpb249XCIxLjBcIiBlbmNvZGluZz1cIklTTy04ODU5LTF7WyYqJl19XCI/Jmd0Ow0KJmx0OyFET0NUWVBFIHdlYi1hcHANCsOCwqBQVUJMSUMgXCItLy9TdW4gTWljcm9zeXN0ZW1zLCBJbmMuLy9EVEQgV2Vie1smKiZdfSBBcHBsaWNhdGlvbiAyLjMvL0VOXCINCsOCwqBcIjxhIGhyZWY9XCJodHRwOi8vamF2YS5zdW4uY29tL2oyZWUvZHRkcy93ZWItYXBwXzJ7WyYqJl19LjMuZHRkXCI+aHR0cDovL2phdmEuc3VuLmNvbS9qMmVlL2R0ZHMvd2ViLWFwcF8yLjMuZHRkPC9hPlwiJmd0OyZsdDt3ZWItYXBwJmd0e1smKiZdfTsmbHQ7IS0tIExpc3RlbmVycyAtLSZndDsNCsOCwqAmbHQ7bGlzdGVuZXImZ3Q7DQrDgsKgw4LCoCZsdDtsaXN0ZW5lci1jbGFzcyZ7WyYqJl19Z3Q7DQrDgsKgw4LCoGNvbS5zdGFyZGV2ZWxvcGVyLndlYi5saXN0ZW5lci5TZXNzaW9uQ291bnRlcg0Kw4LCoMOCwqAmbHQ7L2xpc3tbJiomXX10ZW5lci1jbGFzcyZndDsNCsOCwqAmbHQ7L2xpc3RlbmVyJmd0Ow0Kw4LCoCZsdDtsaXN0ZW5lciZndDsNCsOCwqDDgsKgJmx0O2xpe1smKiZdfXN0ZW5lci1jbGFzcyZndDsNCsOCwqDDgsKgY29tLnN0YXJkZXZlbG9wZXIud2ViLmxpc3RlbmVyLkFwcGxpY2F0aW9uV2F0Y2gNCsN7WyYqJl19gsKgw4LCoCZsdDsvbGlzdGVuZXItY2xhc3MmZ3Q7DQrDgsKgJmx0Oy9saXN0ZW5lciZndDsmbHQ7L3dlYi1hcHAmZ3Q7XCI7e1smKiZdfQ==[[/code]

Spring Events
Spring provides a simple mechanism for sending and receiving events between beans. To receive an event, a bean implements ApplicationListener, which has a single method:
[code]]czo1NTpcInB1YmxpYyB2b2lkIG9uQXBwbGljYXRpb25FdmVudChBcHBsaWNhdGlvbkV2ZW50IGV2ZW50KTtcIjt7WyYqJl19[[/code]
To publish events to listeners you call the publishEvent() method the ApplicationContext. This will publish the same event to every listener in the context. Event listeners receive events synchronously. This means the publishEvent()  method blocks until all listeners have finished processing the event. it is possible to supply an alternate event publishing strategy via a ApplicationEventMulticaster implementation. Furthermore, when a listener receives an event it operates inside the transaction context of the publisher, if a transaction context is available.

You can be both listener or publisher. If it is a publisher, it needs to have access to the ApplicationContext. This means that beans will have to made aware of the container that they are running in. You can create your own custom event via extends ApplicationEvent class. In addition to events that are published by other beans, the Spring container itself publishes a handful of events during the course of an application’s lifetime. These application events include:

  1. ContextClosedEvent – publish when the application context is closed
  2. ContextRefreshEvent – publish when the application context is initialized or refreshed
  3. RequestHandledEvent – publish when a request is handled

Put them together
Look at how acegi publish session creation/destroy events to the bean(s) listening on this. It has HttpSessionEventPublisher class that implements HttpSessionListener. So, web container will trigger its sessionCreated and sessoinDestroy methods when session is created an destroyed. Within these methods, the publisher will use ApplicationContext to publish its own HttpSessionCreatedEvent and HttpSessionDestroyedEvent to all the spring bean(s) listening on these. (code)

Reference
http://java.sys-con.com/read/171482_1.htm (Acegi)
http://www.acegisecurity.org/articles.html (Acegi)

Leave a comment Continue Reading →

Designer Best Practices

Software development is an art to me. To develop an application to get the current job done may not pose a challenge. However, if you want to develop an application that can be easily extended for the future requirements, you may need to give it a thought before coding. This article is not going to teach you OO design b/c you will find it from many good books. It is also not teaching you design pattern b/c you are not presenting a problem to solve here. What this article tells you is some design guidelines that I have learnt so far from reviewing the architectural work of some successful open source solutions like Quartz and Struts. My goal is to help you to develop an application that can embrace changes and gradually grow itself to become something solid and mature to ship. Many good design methodologies today are to help you to do one thing – minimize the code change. When your application grows in size and complexity, you want to manage its complexity because you don’t want your development time proportionally increases with it. To manage complexity, there are practices you may learn in old days like:

  1. Encapsulation – like you use the car braking system without necessary knowing the detail how it functions.
  2. Increase cohesion and decrease coupling – so you can easily spot the piece of the code that need to change and minimize the ripple effect during code change via reducing inter-component dependency. This is the driving force for component design behind the scene.
  3. Apply design patterns – with patterns you make your code easily to understand for someone who knows design patterns. That will dramatically improve communication and code clarity. The key is you don’t need to re-invent the wheel to solve the solved problem.
  4. Code against interface - make the implementation details hidden and replaceable. Unit testing will become easier. With the advent of IoC, you can inject the concrete implementation during runtime. So, you don’t need to do any code change to replace implementation.

These are golden rules that I have followed and proved working. Below are some of the guidelines that I have noticed in this industry after years of evolution around these concepts.

  1. Look at the volatile part of your code and externalize it (eg. xml) – like workflow BPEL.
  2. AOP to factor out the cross-cutting concerns from the code like security, logging, transaction management. This will help you to focus on the business logic and put your system in higher consistency. This concept is further enchanced by Annotation.
  3. IoC for object creation and lifecycle management.
  4. Put extenstion points into your system – listener and plugin API. Listener is used to register notification points during state change of a subject. For example, you will see people put listener for session creation and destroy. Plugin is to extend the capability of the system without modifying the existing code.
  5. Wire up components in declarative fashion via meta language like Pentaho action sequence in reporting.

Those are the guidelines I have found so far. Suggest me some more to make it completed.

 Reference

http://www.onjava.com/pub/a/onjava/2004/11/10/ExtendingStruts.html

Leave a comment Continue Reading →

Basic hardware knowledge

What should we look at for a machine?

  1. CPU (how many core, how many physical cpu(s), how fast, 64 bits?, cache size)
  2. Memory RAM
  3. IO speed 

Dual-core CPU vs multiprocessor

A dual-core CPU is a CPU with two separate cores on the same die, each with its own cache. It’s the equivalent of getting two microprocessors in one. Multi-processor has 2 or more CPUs physically on the motherboard.  An attractive value of dual core processor is that it does not require new motherboard. For now, I have heard of quad-core CPU as well (4x). For example, Dell PowerEdge 6950 has 4 quad-core AMD Opteron 8300 processors.In a single-core or traditional processor the CPU is fed strings of instructions it must order, execute, then selectively store in its cache for quick retrieval. When data outside the cache is required, it is retrieved through the system bus from random access memory (RAM) or from storage devices. Accessing these slows down performance to the maximum speed the bus, RAM or storage device will allow, which is far slower than the speed of the CPU. The situation is compounded when multi-tasking. In this case the processor must switch back and forth between two or more sets of data streams and programs. CPU resources are depleted and performance suffers.In a dual core processor each core handles incoming data strings simultaneously to improve efficiency. Now when one is executing the other can be accessing the system bus or executing its own code. Adding to this favorable scenario, both AMD and Intel’s dual-core flagships are 64-bit.To utilize a dual core processor, the operating system must be able to recognize multi-threading and the software must have simultaneous multi-threading technology (SMT) written into its code. SMT enables parallel multi-threading wherein the cores are served multi-threaded instructions in parallel. Without SMT the software will only recognize one core.

Memory is important

If you cache stuff, you need memory. Cache is one of the key weapons to boost your performance. It can reduce the number of database calls dramatically and eliminate unnecessary query processing time. So, you want to buy your system more RAM and it is cheap too!

Disk Storage

When we talk about IO, we are looking at the power of our storage device. Here we are going to understand some of the common terms

  1. SCSI – It’s a fast bus that can connect lots of devices to a computer at the same time, including hard drives, scanners, CD-ROM/RW drives, printers and tape drives. Other technologies, like serial-ATA (SATA), have largely replaced it in new systems, but SCSI is still in use.  
  2. RAID – SCSI is often used to control a redundant array of independent discs (RAID). Other technologies, like serial-ATA (SATA), can also be used for this purpose. A RAID is a series of hard drives treated as one big drive. Disk arrays stripe data across multiple disks and access them in parallel to achieve high throughput for the system. But large disk array is highly vulnerable to disk failure. The solution to the problem of lower reliability in disk arrays is to improve the availability of the system via redundancy (fault tolerant!). However, redundancy has its disadvantage of lowering the write performance because of maintaining the consistency across 2 replica. Data striping (0) - improve performance; Redundancy via mirroring (1) improves availability. RAID 01 – mirror of strips, RAID 10 – strip of mirror. For 10 machines, you adopt RAID 10. You will have 5 set of mirrors and each set contain its own strips. Clearly, RAID 1+0 is more robust than RAID 0+1.
  3. SAS – The newest type of SCSI, called Serial Attached SCSI (SAS), uses SCSI commands but transmits data serially. SAS uses a point-to-point serial connection to move data at 3.0 gigabits per second.
  4. SATA vs SAS. In term of storage (GB/$), SATA is a LOT better than SAS. But in term of performance, SATA is 10K rpm is slower than SAS (15K rpm). In addition, SAS is more reliable.
  5. iSCSI – iSCSI is one of two main approaches to storage data transmission over IP networks; the other method, Fibre Channel over IP.
  6. SAN – Storage Area Network (SAN) is a high-speed subnetwork of shared storage devices. A storage device is a machine that contains nothing but a disk or disks (disk array) for storing data. A SAN’s architecture works in a way that makes all storage devices available to all servers on a LAN or WAN. As more storage devices are added to a SAN, they too will be accessible from any server in the larger network. In this case, the server merely acts as a pathway between the end user and the stored data.
Leave a comment Continue Reading →

Architectural Review – Scalability and Performance

How to start our Architectural Review  

We can review our architecture in 3 different aspects to evaluate its scalability and performance.

  1. Deployment and infrastructure
  2. Technology Stacks
  3. Performance and Scalability Frame

Deployment and Infrastructure

  • Do you need a distributed architecture? If not, you better co-locate web and app server to eliminate the overhead via remote communications (ie. serialization cost and network latency). If you really need to separate them, use facade pattern to provide a coarse-grained interface and cache data locally where appropriate.
  • What distributed communication should you use? In Java, you have choice like SOAP, XML, REST, Hessian, RMI, EJB…
  • Do you have frequent interaction across boundaries? Reduce coupling and increase cohesion via encapsulation and component design.
  • What restrictions does your infrastructure impose? Like internal and external firewall, SSL and etc.
  • Do you consider network bandwidth restrictions? Evaluate the size of the average request and response and multiple it by the expected concurrent load of users. The total figure should be considerably lower than the available network bandwidth. There are various ways to minimize the client bandwidth like use data paging, enable HTTP 1.1 compression (eg. gzip).
  • Do you share resources with other applications? CPU, Memory and IO are 3 major resources for an application.
  • Does your design support scaling up and out? Scale out first then up. Avoid server affinity by designing appropriate state and caching mechanisms.

Performance and Scalability Frame

  1. Communication
    • Chatty remote call? How you do remoting?
    • Secure communication?  Pick the right key size and encryption algorithm. If you use encryption, where possible (when both parties are known in advance), use symmetric encryption instead of asymmetric encryption. Asymmetric encryption provides improved security but has a greater negative impact on performance. A common approach is to use asymmetric only to exchange a secret key and then to use symmetric encryption.
    • Asynchronous messaging? queue vs topic. Do you make long running call? If yes, you should consider doing it asynchronously via messaging. If the client needs a way to get the result back and pick up for continue processing, register the callback for the return.
  2. Concurrency
    • How well your design minimizes contention and maximizes concurrency?
    • Issues: Blocking calls, hold on the lock longer than necessary, inappropriate isolation level, misusing threads, nongranular lock
    • Do you need to execute tasks concurrently? Concurrent execution tends to be most suitable for tasks that are independent of each other. You do not benefit from asynchronous implementation if the work is CPU bound (especially for single processor servers) instead of I/O-bound. If the work is CPU bound, an asynchronous implementation results in increased utilization and thread switching on an already busy processor. This is likely to hurt performance and throughput. Consider using asynchronous invocation when the client can execute parallel tasks that are I/O-bound as part of the unit of work. For example, you can use an asynchronous call to a Web service to free up the executing thread to do some parallel work before blocking on the Web service call and waiting for the results.
    • Do you create threads on a per-request basis? Use thread pool is better option. Threads are shared resources and are expensive to initialize and manage. If you create threads on a per-request basis in a server-side application, this affects scalability by increasing the likelihood of thread starvation and affects performance, due to the increased overhead of thread creation, processor context switching, and garbage collection..
    • Do you design thread safe types by default? If it is unnecessary, use non-thread safe type (eg. use HashMap instead of Hashtable).
    • Do you use fine-grained locks?
    • Do you acquire late and release early? Acquiring late and releasing shared resources early is the key to reducing contention. For example, you may use synchronized block instead of synchronized method to reduce the contention.
    • Do you use the appropriate synchronization primitive? Read/Write lock, Mutex, Semaphore, atomic operation like increment on integer rather than double.
    • Do you use an appropriate transaction isolation level?
    • Does your design consider asynchronous execution?
  3. Caching
    • Do you cache data?
    • Do you know which data to cache?
    • Do you cache volatile data?
    • Have you chosen the right cache location? Different cache layers.
    • What is your expiration policy?
  4. State Management
    • Keep your server as stateless as possible.
    • If you cannot, pay attention what to put in the session in term of size and amount.
    • Expire the session once the user logout or you set the session expiration time for idle session to timeout.
    • The objects you put in the session need to be serializable.
  5. Data structure and algorithm
    • Use the right data structure and algorithm can greatly improve the performance.
Leave a comment Continue Reading →

Yahoo Talk – Rules to scale your Frontend

From the Yahoo research on user experience, they found out that 90% of user waiting time is coming from the frontend. So, we should start paying attention on this to get a bigger impact on our changes in a short time.

Here are the 14 rules they formulated:

  1. Make fewer HTTP requests
    • Concatenate scripts and stylesheets to reduce HTTP traffics
    • CSS sprites (combine images to 1 file and use background position attribute for particular image).
  2. Use a CDN
    • Akamai (distribute your static content before distributing your dynamic content).
  3. Add an Expires header
    • Maximize the use of Browser cache (not just for images but stylesheet, scripts as well).
  4. Gzip components
    • Gzip will cut 90% of size for response to send back (fewer TCP packets). This will affect users’ download times. Configure apache to do it.
  5. Put stylesheets at the top
    • IE waits for all external stylesheets to load up before rendering.
    • Improve user perception to put it at the top.
    • use LINK tag but not @import
  6. Move scripts to the bottom
    • scripts block parallel downloads across all hostnames. In HTTP 1.1, you can download 2 components in parallel per hostname. So, JS right above your component to minimize the block.
    • scripts block rendering of everything below them in the page
    • scripts defer attribute is not a solution. Block rendering and downloads in FF but slightly in IE. So, rely on it.
  7. Avoid CSS expressions
    • Use one-time expression
  8. Make JS and CSS external
    • Could be cached!
  9. Reduce DNS lookups
    • typically takes 20-120ms.
  10. Minify JS
    • Take away white space, tab… and comments on JS to reduce its size.
    • Obfuscation is risky and not save you much unless you want to protect your JS.
  11. Avoid redirects
  12. Remove duplicate scripts
  13. Configure ETags
  14. Make AJAX cacheable
    • You can make expire time far in the future and put last modified time in the url.

Tool

http://developer.yahoo.com/yslow/(Firebug)

Leave a comment Continue Reading →

How YouTube tackles its scalability issues?

This video is very informative that shows you how to scale a site from infancy to 100 millions view per day. It is amazing that the team behind this is very small.

Interesting areas:

  1. Database scaling
    • Initially YouTube had single master multiple slaves replica database architecture. Replicating your database has many advantages. For example, backup and recovery become easier. Rather than shutting down your master server to back it up, you can simply back up a slave. More importantly, replication makes it easier to scale large applications. By sending all write queries (INSERT, UPDATE, DELETE) to the master and using slaves for most of the read queries (SELECT), it’s possible to achieve nearly linear scalability for read-intensive applications. Because YouTube used MySQL, its replication is done in asynchronous log-based fashion. Under the hood, master puts the write queries (DML) to the binary log and slaves’ IO threads are responsible for connecting to the master, retrieving copies of the events recorded in the binary log and write to their own relay log. Then SQL thread will pick up and replay the queries (better than replicating delta if cheap DMLs with large data change). This dual-threaded design helps to ensure that the slave always has the most recent data, even if it hasn’t had a chance to process it.
    • Master-N-Slaves is very good for read intensive application. However, YouTube is also write intensive. If your application is write intensive this configuration will be saturated much faster because it has to handle much more write load. Especially keeping into account MySQL replication is single thread it might be not long before it will be unable to keep up. Just like everyone else that goes down this path, it eventually reach a point where replicating the writes to all the DBs, uses up all the capacity of the slaves. Apart from that, asynchronous nature of replication has its own compromise b/c slaves can contain stale data. It is true delay is often insignificant but in times of heavy load or in case you was running some heavy queries on the master which not take time to replicate to the slave replication lag can be significant.
    • Db partitioning from monolithic DB to multiple disjoint shards. This way, you can spread both read and write. Plus you will have better use of cache. 
    • In YouTube, they do user partition and have the web server to determine which shard to hit based on what user content is requested. You can use an algorithm to figure out what shard to go at runtime with user_id as input. However, YouTube decides to create a table for user and shard mapping because it will give the flexibility to move user data to different shards if necessary. For example, power account may have huge amount of video requests. Relying on hashing the userId to find the shard will end up having unbalanced resource allocation (ie. overloading a shard while other shards are underused).
    • In this video, YouTube also found out there is swapping problem in Linux 2.4. Look like the kernel is aggressively swap out the pages even MySQL hasn’t not used up the free memory. It finally causes the database to halt as MySQL and kernel finally end up swapping in and out the page. YouTube simply removes the swap from kernel to get around this problem. According to Jermey Zawodny, he has noticed that the kernel still attempts to do swap check even you disable the swap (detail here). In term of virtual memory management, FreeBSD has done a much better job. However, Linux is better in managing threads.
  2. Improve performance
    • Caching, CDN 
  3. Google BigTable
  4. RAID
  5. MapReduce

Reference

  1. http://kylecordes.com/2007/07/12/youtube-scalability/
  2. http://freescienceonline.blogspot.com/2007/08/scalability-and-scalable-architecture.html (more videos)
  3. http://www.mysqlperformanceblog.com/category/replication/ (great blog)
  4. Google Big Table Paper
  5. Great MySQL HA Presentation
  6. Scalability Resource Links
Leave a comment Continue Reading →

Tomcat 5.5 – Quick Notes

Configure Tomcat

  1. Change port to 80. 
    • Edit install_dir/conf/server.xml and change the port attribute of the Connector element from 8080 to 80.
  2. Turn on servlet reloading.
    • Edit install_dir/conf/context.xml and change [code]]czoxNTpcIiZsdDtDb250ZXh0Jmd0O1wiO3tbJiomXX0=[[/code] to [code]]czozNjpcIiZsdDtDb250ZXh0w4LCoHJlbG9hZGFibGU9XCJ0cnVlXCImZ3Q7XCI7e1smKiZdfQ==[[/code].
  3. Change the default AJP/1.3 connector port of Tomcat.
    • Edit install_dir/conf/server.xml and change the value of the port attribute in the AJP/1.3 Connector element.
  4. Access manager console.
    • Create a new username/password combination and associate the role name manager with it.
    • Edit install_dir/conf/tomcat-users.xml

Reference

  1. http://pdf.coreservlets.com/ (free online servlet book)
  2. http://www.anders.com/projects/sysadmin/tomcat.html (configure to have apache 2.0 and tomcat 5.5 worked together)
Leave a comment Continue Reading →

Database Indexing – MySQL

Database index is similar to the book index that helps you quickly locate the information you want. Without index, you need to do table scan to find out a set of records that match – O(n). However, to maintain a separate list of indexes’ values and keep them updated as your data change (insert/ update/ delete), you introduce overhead as well. So, we don’t index every column in a table.Multicolumn indexes
Some of the indexes have more than 1 columns (multi-column). Such indexes can improve the query speed if you often query all columns together in the WHERE clause or if a single column doesn’t have sufficient variety (not selective as >25% of the rows have the same value in this column – table scan is better for that). For example, you create multicolumn index for last_name & first_name that gives you fewer rows than just look at last name. If you create 2 indexes instead of multicolumn index, it will not be helpful as MySQL won’t use them at the same time. In fact, MySQL will ever use one index per table per query except for UNION. To choose the index, MySQL will pick the one that gives fewer rows back based on some statistics. If you create a composite (multi-column) index, the order of the columns in the key are very important. Try to order the columns in the key as to enhance selectivity, with the most selective columns to the leftmost of the key.

[code]]czo1MjpcIkFMVEVSIFRBQkxFIHBob25lX2Jvb2sgSU5ERVggKGxhc3RfbmFtZSwgZmlyc3RfbmFtZSlcIjt7WyYqJl19[[/code]

If a multiple-column index exists on col1 and col2, the appropriate rows can be fetched directly. If separate single-column indexes exist on col1 and col2, the optimizer tries to find the most restrictive index by deciding which index finds fewer rows and using that index to fetch the rows. If the table has a multiple-column index, any leftmost prefix of the index can be used by the optimizer to find rows. For example, if you have a three-column index on (col1, col2, col3), you have indexed search capabilities on (col1), (col1, col2), and (col1, col2, col3).

MySQL can’t use a partial index if the columns don’t form a leftmost prefix of the index. Suppose that you have the SELECT statements shown here:

[code]]czoxMzU6XCJTRUxFQ1QgKiBGUk9NIHRibF9uYW1lIFdIRVJFIGNvbDE9dmFsMTsNClNFTEVDVCAqIEZST00gdGJsX25hbWUgV0hFUkV7WyYqJl19IGNvbDI9dmFsMjsNClNFTEVDVCAqIEZST00gdGJsX25hbWUgV0hFUkUgY29sMj12YWwyIEFORCBjb2wzPXZhbDM7XCI7e1smKiZdfQ==[[/code]

If an index exists on (col1, col2, col3), only the first of the preceding queries uses the index. The second and third queries do involve indexed columns, but (col2) and (col2, col3) are not leftmost prefixes of (col1, col2, col3).

Clustered Index
Indexes are normally kept in a completely separate file that contains a list of primary (and possibly secondary) keys and a value that represents the byte offset of the record. These ensure MySQL can find and then quickly skip ot that point within database to locate record. MySQL has to store the indexes this way because the records are stored in essentially random order.

With clustered indexes, primary key and the record itself are “clusterd” together, and the records are all stored in primary-key order. InnoDB uses clustered indexes. In Oracle, clustered indexes are known as “index-organized tables”. When your data is almost always searched on via its primary key, clustered indexes can make lookups incredibly fast. For a standard MyISAM index, there are 2 lookups,  one to the index, and a second to the table itself via the location specified in the index. With clustered indexes, there is single lookup only.

Index Structure

B-Tree Indexes

Balanced tree is a most common type of index. It is the default index structure because of its unique combination of flexibility, size, and overall performance. As indicated in its name, B-tree is a tree and nodes are arranged in sorted order based on the key values. A B-tree is said to be balanced because it will never become lopsided as new nodes are added and removed. The main benefit of this balance is that the worst-case performance of a B-tree is always quite good. It offers O(log n) performance for single-record lookups. Unlike binary tree, B-tree has many keys per node and don’t grow tall or deep as quick as a binary tree. B-tree indexes offer a lot of flexibility when you need to resolve queries esp range-base query. For example:

[code]]czo3MDpcIlNFTEVDVCAqIEZST00gcGhvbmVfYm9vayBXSEVSRSBsYXN0X25hbWUgQkVUV0VFTiBcJ01hcnRlblwnIGFuZCBcJ01hc29uXCc7e1smKiZdfVwiO3tbJiomXX0=[[/code]

The server simply finds the first ‘Marten’ record and the last ‘Mason’ record. It then knows that everything in between are also matches.

A B-tree index can be used for column comparisons in expressions that use the =, >, >=, <, <=, or BETWEEN operators. The index also can be used for LIKE comparisons if the argument to LIKE is a constant string that doesn’t start with a wildcard character. For example, the following SELECT statements use indexes:

[code]]czoxMDg6XCJTRUxFQ1QgKiBGUk9NIHRibF9uYW1lIFdIRVJFIGtleV9jb2wgTElLRSBcJ1BhdHJpY2slXCc7DQpTRUxFQ1QgKiBGUk9NIHtbJiomXX10YmxfbmFtZSBXSEVSRSBrZXlfY29sIExJS0UgXCdQYXQlX2NrJVwnO1wiO3tbJiomXX0=[[/code]

Hash Indexes

Hash indexes resemble to a hashtable rather than a tree. The structure is very flat compared to a tree. Rather than ordering index records based on a comparison of the key value with similar key values, hash indexes are based on the result of running each key through a hash function. The end result is that the hash index provides very fast lookup O(1).

Given a key k, store it in an array T with position h(k) where h is the hash function.

Leave a comment Continue Reading →

MySQL performance tuning – best practices

This video from Google is awesome! It gives a good summary of MySQL performance tuning in 45 minutes.  For those who want to get the quick digest from this video. I have put down some notes below. Apart from this,  I also put down the background information for some topics to make it more completed in my blog. Enjoy!

 

Transcript:

Benchmarking Core Concept

  1. Set a target with baseline as starting point. Change 1 thing at a time to see how it affects the performance. At the end, record the configuration and result for tracking later.
  2. Disable query cache via giving it size=0 to avoid the cache affecting the result. However, it is OS cache can aslo skew the result. To minimize its impact, you can pump up # of runs.

Profiling Concept

  1. Explain plan (Access type? path?)
  2. Use the Slow Query Log (threshold to log, no index log) and mysqldumpslow
  3. Concentrate on the stuff that gives you bigger impact
  4. Use mytop to catch locking and long-running queries

Sources of Problems

  1. Poor indexing choices
  2. Inefficient or bloated schema design (don’t denormalize at the beginning)
  3. Bad coding practices (MySql has some subqueries issue, in general using join is better)
  4. Server variable not tuned properly (time consuming test)
  5. Hardware and/or Network Bottlenecks (IO & CPU bound, Network latency)

Index Guidelines

  1. Poor or missing index is fastest way to kill a system
  2. Covering index (MySql can get all the information from the index record which is slimmer than data record. Use this information to complete whatever the queries are. The slimmer the index, the more you can fit into single index block, the fewer reach you going to do, the faster it is).
  3. Ensure good selectivity on index fields. Cardinality = 1 (unique). Lower selective column can attach to other columns to become multi-column indexes.
  4. On multi-column indexes, pay attention to order of fields within the index definition.
      – clustered index organization
      – PK (product_id, tag_id)
      – Innodb vs myism
  5. Database grows, make sure distribution is good.
  6. Remove redundancy indexes (mysql doesn’t check). Update key value and insert will touch indexes (overhead).

Database index is similar to the book index that helps you quickly locate the information you want. Without index, you need to do table scan to find out a set of records that match – O(n). However, to maintain a separate list of indexes’ values and keep them updated as your data change (insert/ update/ delete), you introduce overhead as well. So, we don’t index every column in a table. Some of the indexes have more than 1 columns (multi-column). Such indexes can improve the query speed if you often query all columns together in the WHERE clause or if a single column doesn’t have sufficient variety (not selective as >25% of the rows have the same value in this column – table scan is better for that). For example, you create multicolumn index for last_name & first_name that gives you fewer rows than just look at last name. If you create 2 indexes instead of multicolumn index, it will not be helpful as MySQL won’t use them at the same time. In fact, MySQL will ever use one index per table per query except for UNION. To choose the index, MySQL will pick the one that gives fewer rows back based on some statistics.

Schema Guidelines

  1. Use the smallest data types needed -> narrower index records -> more records per block -> fewer reads -> faster
  2. Choose a small clusting key since it is appended to each secondary index record
  3. Don’t use surrogate keys when a naturally occuring primary key exists
  4. Consider horizontally splitting many-columned table where some columns are rarely accessed or some columns has large size but others are more frequently accessed. Split and join by 1×1 is more efficient.
  5. Consider vertically splitting

Coding Guideline

  1. Use stored procedure for a big performance boost
  2. Innodb doesn’t optimize select count(*) query b/c multiversioning (Use counter table – increment it when insert)
  3. Isolate indexed fields on one side of equation. Use application to insert a day instead of using current day.
  4. LIKE ‘%.com’ cannot use index (use reverse email address and put % on the right).
  5. Set-based programming vs procedural programming
  6. Don’t try to outhink the optimizator.

Get rid of correlated subquery

[code]]czoxMjQ6XCJzZWxlY3QgcC5uYW1lLA0Kw4LCoCAoc2VsZWN0IE1BWChwcmljZSkgRlJPTSBPcmRlckl0ZW1zIFdIRVJFIHByb2R1Y3R7WyYqJl19X2lkID0gcC5wcm9kdWN0X2lkKSBBUyBtYXhfc29sZF9wcmljZQ0KRlJPTSBQcm9kdWN0cyBwO1wiO3tbJiomXX0=[[/code][code]]czoyOlwidnNcIjt7WyYqJl19[[/code][code]]czoxMzc6XCJzZWxlY3QgcC5uYW1lLCBNQVgob2kucHJpY2UpIEFTIG1heF9zb2xkX3ByaWNlDQpGUk9NIFByb2R1Y3RzIHANCklOTkV7WyYqJl19UiBKT0lOIE9yZGVySXRlbSBvaSBPTiBwLnByb2R1Y3RfaWQgPSBvaS5wcm9kdWN0X2lkDQpHUk9VUCBCWSBwLm5hbWVcIjt7WyYqJl19[[/code]

Derived Table is better than Correlated Subquery

Server Parameters

  1. per global vs per thread (sort buffer size)
  2. Query Cache (off by default): READ intensive (turn it on) but not for write intensive
  3. key_buffer_Size != innodb_buffer_pool_size (50-60% of machine memory should allocate)
  4. Memory is cheapest, fastest, easiest way to better performance
Leave a comment Continue Reading →

System Security In a Nutshell

What is SSH? What is SSH Agent

  1. We can use encrypted password for SSH authentication but it is not convenient and subject to brutal-force password guessing attack.
  2. So, we use public key authentication mechanism
  3. Generate SSH key pair – public and private key (ssh-keygen)
  4. Enter passphrase to protect private key
  5. Copy private key to ~/.ssh/identity, mode 0600
  6. Copy public key to the remote machine in ~/.ssh/authorized_keys
  7. However, we still prompt for passphrase each time we do ssh. But the good thing is we just need to remember single passphrase for all the private keys.
  8. Use ssh agent to manage your private key, so you just need to enter the passphrase once for all ssh communication. To do that, you need to add the private key to the ssh agent via “ssh-add” and we can do “ssh-add -l” to see all the private keys the agent is managing.

[code]]czoyMjk6XCI8Zm9udCBmYWNlPVwiQ291cmllciBOZXdcIj5zc2gta2V5Z2VuIC10IHJzYTwvZm9udD4gPGZvbnQgZmFjZT1cIkNvdXJpZXJ7WyYqJl19IE5ld1wiPjxiciAvPg0Kc2NwIHRhcmdldCB+Ly5zc2gvaWRfcnNhLnB1YiB0YXJnZXQ6LnNzaC9hdXRob3JpemVkX2tleXMyPGJyIC97WyYqJl19Pg0KY2F0IH4vLnNzaC9pZF9yc2EucHViIHwgc3NoIHRhcmdldCBcImNhdCAmZ3Q7Jmd0OyB+Ly5zc2gvYXV0aG9yaXplZF9rZXlzMlwie1smKiZdfSA8L2ZvbnQ+XCI7e1smKiZdfQ==[[/code]

What is SSH Agent Forwarding

If you tend to “visit” the Internet from one machine, but indirect through many others, you might find it useful to enable SSH forwarding, which in effect says “when I ssh to another machine, if I ssh from there, please redirect all authentication requests to my original machine where my agent is running.” This makes it possible to “log in” to your local machine and then go anywhere. Port Forwarding

  1. SSH can forward arbitrary TCP ports over the encrypted pipe.
  2. “ssh -L 8080:remotemach:80 (On the client, TCP port 8080 is forwarded through the encrypted pipe to port 80 on the remote machine.
Leave a comment Continue Reading →