پایگاه داده معمولاً یکی از بخشهای کند در عملکرد نرمافزارها است. داشتن پایگاه دادهای که خوب بهینه شده باشد برای سیستمهای پرسرعت ضروری است. در ادامه چند تکنیک کاربردی برای بهینهسازی پایگاه داده معرفی میکنم:
ایجاد ایندکسها: ایندکسها مثل فهرست هستند و به پایگاه داده کمک میکنند که اطلاعات موردنیاز را سریعتر پیدا کند. با مرتب کردن دادهها، ایندکسها باعث میشوند تا پایگاه داده راحتتر سطرهایی را که شرط WHERE را دارند پیدا کند و سرعت کوئریهای SELECT افزایش یابد. البته، ایندکسها ممکن است سرعت عملیات نوشتن (مثل INSERT و UPDATE) را کمی کند کنند، پس باید بین سرعت خواندن و نوشتن تعادل برقرار کنیم.
CREATE INDEX idx_username ON users(username);
ایندکسهای ترکیبی: ایندکسهای ترکیبی شامل چند ستون هستند و برای وقتی که در کوئریها باید چند شرط مختلف بررسی یا دادهها بر اساس چند ستون مرتب شوند، کاربرد دارند. این کار باعث میشود به جای ایندکسهای جداگانه روی هر ستون، فقط یک ایندکس استفاده کنیم و پایگاه داده سریعتر به نتیجه برسد.
CREATE INDEX idx_name_age ON employees(name, age);
نرمالسازی (Normalization): این فرآیند دادهها را به گونهای سازماندهی میکند که از تکرار و وابستگیهای غیرضروری کاسته شود و احتمال خطا در دادهها کاهش یابد. با تقسیم جداول بزرگ به جداول کوچک و مرتبط، نرمالسازی به یکپارچگی دادهها کمک میکند. البته، ممکن است کوئریها را پیچیدهتر کند.
مثال کد SQL (Normalization در فرم سوم):
CREATE TABLE customers ( customer_id INT PRIMARY KEY, customer_name VARCHAR(100), address VARCHAR(255) ); CREATE TABLE orders ( order_id INT PRIMARY KEY, customer_id INT, order_date DATE, FOREIGN KEY (customer_id) REFERENCES customers(customer_id) );
دنرمالسازی (Denormalization): در حالی که نرمالسازی از تکرار دادهها جلوگیری میکند، دنرمالسازی با افزودن تکرار بهصورت کنترلشده، سرعت کوئریها را (بهویژه برای عملیات خواندن زیاد) افزایش میدهد. این کار ممکن است شامل افزودن ستونها یا جداول تکراری به شکل استراتژیک باشد تا دسترسی به دادهها سریعتر انجام شود.
CREATE TABLE denormalized_orders ( order_id INT PRIMARY KEY, customer_id INT, customer_name VARCHAR(100), order_date DATE );
بهینهسازی کوئریها: کوئریهایی که زیاد استفاده میشوند را بهطور مرتب بررسی و بهینهسازی کنید. از ابزارهایی مثل EXPLAIN استفاده کنید تا برنامه اجرای کوئری را ببینید و نقاط قابل بهبود را شناسایی کنید.
EXPLAIN SELECT * FROM orders WHERE customer_id = 123;
**اجتناب از استفاده از SELECT ***: بهجای انتخاب همه ستونها، فقط ستونهای موردنیاز را بازیابی کنید. این کار مقدار دادههای منتقلشده و پردازششده را کاهش میدهد و عملکرد کوئری را بهبود میبخشد.
SELECT order_id, order_date FROM orders WHERE customer_id = 123;
پارتیشنبندی جداول: پارتیشنبندی به معنای تقسیم جداول بزرگ به قطعات کوچکتر و قابل مدیریتتر است. این کار میتواند عملکرد کوئری را بهطور قابلتوجهی بهبود بخشد، زیرا موتور پایگاه داده میتواند بر روی زیرمجموعههای کوچکتر داده کار کند و به این ترتیب زمان اجرای کوئری کاهش مییابد.
CREATE TABLE sales ( sale_id INT PRIMARY KEY, sale_date DATE, amount DECIMAL(10, 2) ) PARTITION BY RANGE (YEAR(sale_date)) ( PARTITION p0 VALUES LESS THAN (1990), PARTITION p1 VALUES LESS THAN (2000), PARTITION p2 VALUES LESS THAN (2010), PARTITION p3 VALUES LESS THAN (2020), PARTITION p4 VALUES LESS THAN (MAXVALUE) );
پارتیشنپروینیگ (Partition Pruning): اطمینان حاصل کنید که برنامهریز کوئری در حین اجرای کوئری، پارتیشنهای غیرضروری را حذف میکند. این کار از اسکن کل مجموعه داده جلوگیری میکند و به بهبود عملکرد کمک میکند.
SELECT * FROM sales WHERE sale_date >= '2022-01-01' AND sale_date < '2023-01-01';
کشینگ کوئری: یک مکانیزم کش برای ذخیره نتایج کوئریهای پرکاربرد پیادهسازی کنید. این کار بار روی پایگاه داده را کاهش میدهد و با ارائه نتایج کششده، زمان پاسخگویی را افزایش میدهد.
-- Pseudocode DECLARE @cacheKey NVARCHAR(255) = 'query_cache_key'; DECLARE @cachedResult NVARCHAR(MAX); SET @cachedResult = REDIS.GET(@cacheKey); IF @cachedResult IS NULL BEGIN -- Execute the query and store the result in the cache SET @cachedResult = EXECUTE_QUERY('SELECT * FROM large_table'); REDIS.SET(@cacheKey, @cachedResult, EXPIRY_TIME); END -- Use @cachedResult for further processing
کشینگ شیء (Object Caching): اشیاء یا دادههای پرکاربرد را در لایه اپلیکیشن کش کنید تا تعداد کوئریها به پایگاه داده کاهش یابد. این کار میتواند با استفاده از کتابخانهها یا فریمورکهای کشینگ در حافظه انجام شود.
from django.core.cache import cache def get_user_data(user_id): # Try to fetch user data from cache user_data = cache.get(f'user_{user_id}') if user_data is None: # If not in cache, fetch from the database user_data = User.objects.get(id=user_id) # Store the data in cache for future requests cache.set(f'user_{user_id}', user_data, TIMEOUT) return user_data
بهروزرسانی آمار: بهروز نگهداشتن آمار برای برنامهریز کوئری بسیار مهم است تا تصمیمات بهتری درباره برنامههای اجرایی بگیرد. بهطور منظم آمار را بهروزرسانی کنید تا از بهینهسازی دقیق و کارآمد کوئریها اطمینان حاصل شود.
-- Update statistics for a table UPDATE STATISTICS table_name;
بایگانی دادهها: دادههای قدیمی که دیگر به آنها نیازی نیست را بایگانی یا حذف کنید. این کار میتواند عملکرد کوئریها را بهبود بخشد و نیاز به فضای ذخیرهسازی را کاهش دهد، بهویژه در سیستمهایی که دارای مجموعهدادههای تاریخی بزرگ هستند.
-- Archive data older than a certain date DELETE FROM historical_data WHERE date < '2020-01-01';
بهینهسازی پیکربندی سرور: تنظیمات و پیکربندیهای سرور پایگاه داده را بر اساس بار کاری و قابلیتهای سختافزاری تنظیم کنید. این شامل پارامترهایی مانند اندازه بافرها، تنظیمات کش و محدودیتهای اتصال میشود.
-- Example: Increase the size of the query cache SET GLOBAL query_cache_size = 256M;
استفاده از SSDها: از درایوهای حالت جامد (SSDs) برای ذخیرهسازی استفاده کنید. SSDها بهطور قابل توجهی نسبت به درایوهای سخت (HDDها) دسترسی سریعتری به دادهها ارائه میدهند که منجر به بهبود عملکرد کلی پایگاه داده میشود.
سطوح ایزولاسیون: سطوح ایزولاسیون را بر اساس نیازهای اپلیکیشن خود تنظیم کنید. سطوح ایزولاسیون کنترل میکنند که تغییرات ایجاد شده توسط یک تراکنش برای سایر تراکنشها چقدر قابل مشاهده باشد. انتخاب سطح ایزولاسیون مناسب برای برقراری تعادل بین سازگاری و عملکرد بسیار مهم است.
-- Set isolation level to READ COMMITTED SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
Using Connection Pooling: از اتصالهای پایگاه داده استفاده مجدد کنید تا از بار اضافی ایجاد اتصالهای جدید برای هر درخواست جلوگیری شود. اتصالهای استخر به بهینهسازی مدیریت و استفاده مجدد از اتصالات پایگاه داده کمک میکنند و از این رو عملکرد کلی اپلیکیشن را بهبود میبخشند.
// Example using Node.js with mysql2 const pool = mysql.createPool({ host: 'localhost', user: 'root', password: 'password', database: 'my_database', connectionLimit: 10 }); // Using a connection from the pool pool.getConnection((err, connection) => { if (err) throw err; // Use the connection connection.query('SELECT * FROM users', (error, results) => { // Release the connection back to the pool connection.release(); }); });
بهینهسازی پایگاه داده یک فرآیند مستمر است که شامل ارزیابی و بهبود مداوم است. با پیادهسازی این تکنیکها میتوانید عملکرد پایگاه داده را بهبود بخشید و تجربه کاربری بهتری برای کاربران خود فراهم کنید. توجه داشته باشید که انتخاب تکنیکها باید بر اساس نیازهای خاص اپلیکیشن شما و نوع بار کاری انجام شود.
منبع: وبسایت میموک