|
| 1 | +# Database Performance Features - Quick Start Guide |
| 2 | + |
| 3 | +This guide explains how to use the new database performance features in pH7Builder v18. |
| 4 | + |
| 5 | +## 🚀 Features Overview |
| 6 | + |
| 7 | +### 1. Database Load Balancer |
| 8 | +Routes database queries to appropriate servers: |
| 9 | +- **Write queries** → Master database |
| 10 | +- **Read queries** → Slave databases (round-robin) |
| 11 | +- **Automatic failover** if slaves are unavailable |
| 12 | + |
| 13 | +### 2. Connection Pooling |
| 14 | +Maintains a pool of reusable database connections: |
| 15 | +- Reduces connection overhead |
| 16 | +- Configurable pool size |
| 17 | +- Automatic connection health checks |
| 18 | + |
| 19 | +### 3. Enhanced File Operations |
| 20 | +Better error handling for file operations: |
| 21 | +- Detailed error messages with constants |
| 22 | +- Automatic validation and logging |
| 23 | +- Standardized JSON error responses |
| 24 | + |
| 25 | +## 📋 Quick Setup |
| 26 | + |
| 27 | +### Option 1: Using Environment Variables (Recommended) |
| 28 | + |
| 29 | +Add to your `.env` file or server configuration: |
| 30 | + |
| 31 | +```bash |
| 32 | +# Enable load balancing |
| 33 | +DB_ENABLE_LOAD_BALANCING=true |
| 34 | +DB_MASTER_HOST=master.example.com |
| 35 | +DB_SLAVE_HOSTS=slave1.example.com,slave2.example.com |
| 36 | + |
| 37 | +# Enable connection pooling |
| 38 | +DB_ENABLE_CONNECTION_POOL=true |
| 39 | +DB_POOL_SIZE=15 |
| 40 | +``` |
| 41 | + |
| 42 | +Then add to `_protected/app/Bootstrap.php`: |
| 43 | + |
| 44 | +```php |
| 45 | +// After Db::getInstance() call |
| 46 | +if (getenv('DB_ENABLE_LOAD_BALANCING') === 'true') { |
| 47 | + require PH7_PATH_APP . 'configs/bootstrap-integration.example.php'; |
| 48 | +} |
| 49 | +``` |
| 50 | + |
| 51 | +### Option 2: Direct Configuration |
| 52 | + |
| 53 | +In `_protected/app/Bootstrap.php`, after database initialization: |
| 54 | + |
| 55 | +```php |
| 56 | +use PH7\Framework\Mvc\Model\Engine\Db; |
| 57 | + |
| 58 | +// Enable load balancing |
| 59 | +Db::enableLoadBalancer( |
| 60 | + [ |
| 61 | + 'dsn' => 'mysql:host=master.db;dbname=ph7cms', |
| 62 | + 'username' => 'user', |
| 63 | + 'password' => 'pass', |
| 64 | + 'options' => [] |
| 65 | + ], |
| 66 | + [ |
| 67 | + ['dsn' => 'mysql:host=slave1.db;dbname=ph7cms', 'username' => 'user', 'password' => 'pass'], |
| 68 | + ['dsn' => 'mysql:host=slave2.db;dbname=ph7cms', 'username' => 'user', 'password' => 'pass'] |
| 69 | + ] |
| 70 | +); |
| 71 | + |
| 72 | +// Enable connection pooling |
| 73 | +Db::enableConnectionPool(10); |
| 74 | +``` |
| 75 | + |
| 76 | +## 💡 Usage Examples |
| 77 | + |
| 78 | +### Using PerformanceHelper (Easiest) |
| 79 | + |
| 80 | +```php |
| 81 | +use PH7\Framework\Mvc\Model\Engine\Util\PerformanceHelper; |
| 82 | + |
| 83 | +// Read query (automatically uses slave if available) |
| 84 | +$oStmt = PerformanceHelper::queryRead( |
| 85 | + 'SELECT * FROM users WHERE active = :active', |
| 86 | + [':active' => 1] |
| 87 | +); |
| 88 | +$aUsers = $oStmt->fetchAll(PDO::FETCH_OBJ); |
| 89 | + |
| 90 | +// Write query (automatically uses master) |
| 91 | +PerformanceHelper::queryWrite( |
| 92 | + 'UPDATE users SET lastLogin = NOW() WHERE id = :id', |
| 93 | + [':id' => $iUserId] |
| 94 | +); |
| 95 | + |
| 96 | +// Batch reads for better performance |
| 97 | +$aResults = PerformanceHelper::batchRead([ |
| 98 | + ['query' => 'SELECT COUNT(*) FROM users'], |
| 99 | + ['query' => 'SELECT * FROM settings WHERE active = 1'] |
| 100 | +]); |
| 101 | +``` |
| 102 | + |
| 103 | +### Direct Database Connection |
| 104 | + |
| 105 | +```php |
| 106 | +use PH7\Framework\Mvc\Model\Engine\Db; |
| 107 | + |
| 108 | +// Get connection for reading |
| 109 | +$oReadConn = Db::getConnection(false); |
| 110 | +$oStmt = $oReadConn->prepare('SELECT * FROM users'); |
| 111 | +$oStmt->execute(); |
| 112 | + |
| 113 | +// Get connection for writing |
| 114 | +$oWriteConn = Db::getConnection(true); |
| 115 | +$oStmt = $oWriteConn->prepare('INSERT INTO logs VALUES (...)'); |
| 116 | +$oStmt->execute(); |
| 117 | +``` |
| 118 | + |
| 119 | +### File Operations with Better Errors |
| 120 | + |
| 121 | +```php |
| 122 | +use PH7\Framework\File\File; |
| 123 | + |
| 124 | +$oFile = new File(); |
| 125 | +$mResult = $oFile->putFile('/path/to/file.txt', 'content'); |
| 126 | + |
| 127 | +if (is_array($mResult) && isset($mResult['error'])) { |
| 128 | + // Detailed error with automatic logging |
| 129 | + $this->displayError($mResult['error']); |
| 130 | +} else { |
| 131 | + // Success |
| 132 | + $this->displaySuccess("File written successfully"); |
| 133 | +} |
| 134 | +``` |
| 135 | + |
| 136 | +## 📊 Monitoring Performance |
| 137 | + |
| 138 | +### Get Statistics |
| 139 | + |
| 140 | +```php |
| 141 | +use PH7\Framework\Mvc\Model\Engine\Util\PerformanceHelper; |
| 142 | + |
| 143 | +$aStats = PerformanceHelper::getPerformanceStats(); |
| 144 | + |
| 145 | +echo "Query Count: " . $aStats['query_count'] . "\n"; |
| 146 | +echo "Query Time: " . $aStats['query_time'] . "s\n"; |
| 147 | + |
| 148 | +// Load balancer stats |
| 149 | +if ($aStats['load_balancer']) { |
| 150 | + print_r($aStats['load_balancer']); |
| 151 | +} |
| 152 | + |
| 153 | +// Connection pool stats |
| 154 | +if ($aStats['connection_pool']) { |
| 155 | + print_r($aStats['connection_pool']); |
| 156 | +} |
| 157 | +``` |
| 158 | + |
| 159 | +### Create Admin Dashboard Widget |
| 160 | + |
| 161 | +Add to your admin panel: |
| 162 | + |
| 163 | +```php |
| 164 | +$aStats = \PH7\Framework\Mvc\Model\Engine\Db::getLoadBalancerStats(); |
| 165 | + |
| 166 | +echo "<div class='stats-widget'>"; |
| 167 | +echo "<h3>Database Performance</h3>"; |
| 168 | +echo "<p>Master Nodes: {$aStats['master_nodes']}</p>"; |
| 169 | +echo "<p>Slave Nodes: {$aStats['slave_nodes']}</p>"; |
| 170 | +echo "<p>Active Connections: {$aStats['active_slave_connections']}</p>"; |
| 171 | +echo "</div>"; |
| 172 | +``` |
| 173 | + |
| 174 | +## 🔧 Configuration Tips |
| 175 | + |
| 176 | +### For Small Sites (< 1000 daily visitors) |
| 177 | +- **Connection Pool**: Yes (size: 5-10) |
| 178 | +- **Load Balancer**: Not necessary |
| 179 | + |
| 180 | +### For Medium Sites (1000-10000 daily visitors) |
| 181 | +- **Connection Pool**: Yes (size: 10-20) |
| 182 | +- **Load Balancer**: Optional (if you have replication) |
| 183 | + |
| 184 | +### For Large Sites (> 10000 daily visitors) |
| 185 | +- **Connection Pool**: Yes (size: 20-50) |
| 186 | +- **Load Balancer**: Highly recommended (2-3 slaves minimum) |
| 187 | + |
| 188 | +### Pool Size Guidelines |
| 189 | +- Calculate: `(concurrent_users / 10) + 5` |
| 190 | +- Monitor in-use connections |
| 191 | +- Increase if you see pool exhaustion errors |
| 192 | + |
| 193 | +## ⚠️ Important Notes |
| 194 | + |
| 195 | +1. **Load balancing requires MySQL replication** to be properly configured |
| 196 | +2. **Test thoroughly** in development before production |
| 197 | +3. **Monitor statistics** to optimize configuration |
| 198 | +4. **Backup before enabling** new features |
| 199 | +5. **Read operations** include: SELECT, SHOW, DESCRIBE |
| 200 | +6. **Write operations** include: INSERT, UPDATE, DELETE, CREATE, ALTER, DROP |
| 201 | + |
| 202 | +## 🐛 Troubleshooting |
| 203 | + |
| 204 | +### Load Balancer Issues |
| 205 | +```php |
| 206 | +// Check if load balancer is working |
| 207 | +$aStats = Db::getLoadBalancerStats(); |
| 208 | +if ($aStats === null) { |
| 209 | + echo "Load balancer not enabled"; |
| 210 | +} |
| 211 | +``` |
| 212 | + |
| 213 | +### Connection Pool Issues |
| 214 | +```php |
| 215 | +// Check pool statistics |
| 216 | +$aStats = Db::getConnectionPoolStats(); |
| 217 | +if ($aStats['in_use_connections'] >= $aStats['max_pool_size']) { |
| 218 | + echo "Pool size too small, increase it!"; |
| 219 | +} |
| 220 | +``` |
| 221 | + |
| 222 | +### File Operation Errors |
| 223 | +All file errors are automatically logged. Check: |
| 224 | +- `_protected/data/log/pH7log/logfile.log` |
| 225 | + |
| 226 | +## 📚 Additional Resources |
| 227 | + |
| 228 | +- Full documentation: `/V18-PERFORMANCE-IMPROVEMENTS.md` |
| 229 | +- Configuration examples: `/_protected/app/configs/database-advanced.example.php` |
| 230 | +- Bootstrap integration: `/_protected/app/configs/bootstrap-integration.example.php` |
| 231 | + |
| 232 | +## 🎯 Best Practices |
| 233 | + |
| 234 | +1. ✅ Use `PerformanceHelper` for cleaner code |
| 235 | +2. ✅ Enable connection pooling first, test, then add load balancing |
| 236 | +3. ✅ Monitor statistics regularly |
| 237 | +4. ✅ Use read connections for all SELECT queries |
| 238 | +5. ✅ Use write connections for all INSERT/UPDATE/DELETE |
| 239 | +6. ✅ Check file operation results for error arrays |
| 240 | +7. ✅ Set appropriate pool sizes based on traffic |
| 241 | +8. ✅ Configure health checks for database nodes |
| 242 | + |
| 243 | +## 🔄 Migration from Old Code |
| 244 | + |
| 245 | +Old code continues to work without changes: |
| 246 | + |
| 247 | +```php |
| 248 | +// Old way (still works) |
| 249 | +$oDb = Db::getInstance(); |
| 250 | +$oStmt = $oDb->prepare('SELECT * FROM users'); |
| 251 | + |
| 252 | +// New way (optimized) |
| 253 | +$oStmt = PerformanceHelper::queryRead('SELECT * FROM users'); |
| 254 | +``` |
| 255 | + |
| 256 | +Both methods work, but the new way automatically benefits from load balancing if enabled. |
0 commit comments