Mysql
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Mysql

Hiệu suất của truy vấn trên cột Boolean được lập chỉ mục so với cột Ngày giờ

Đây là điểm chuẩn MariaDB (10.0.19) với 10 triệu hàng (sử dụng plugin trình tự ):

drop table if exists test;
CREATE TABLE `test` (
    `id` MEDIUMINT UNSIGNED NOT NULL,
    `is_active` TINYINT UNSIGNED NOT NULL,
    `deleted_at` TIMESTAMP NULL,
    PRIMARY KEY (`id`),
    INDEX `is_active` (`is_active`),
    INDEX `deleted_at` (`deleted_at`)
) ENGINE=InnoDB
    select seq id
        , rand(1)<0.5 as is_active
        , case when rand(1)<0.5 
            then null
            else '2017-03-18' - interval floor(rand(2)*1000000) second
        end as deleted_at
    from seq_1_to_10000000;

Để đo thời gian, tôi sử dụng set profiling=1 và chạy show profile sau khi thực hiện một truy vấn. Từ kết quả cấu hình, tôi lấy giá trị của Sending data vì mọi thứ khác hoàn toàn nhỏ hơn một mili giây.

TINYINT chỉ mục:

SELECT COUNT(*) FROM test WHERE is_active = 1;

Thời gian chạy:~ 738 mili giây

TIMESTAMP chỉ mục:

SELECT COUNT(*) FROM test WHERE  deleted_at is null;

Thời gian chạy:~ 748 mili giây

Kích thước chỉ mục:

select database_name, table_name, index_name, stat_value*@@innodb_page_size
from mysql.innodb_index_stats 
where database_name = 'tmp'
  and table_name = 'test'
  and stat_name = 'size'

Kết quả:

database_name | table_name | index_name | stat_value*@@innodb_page_size
-----------------------------------------------------------------------
tmp           | test       | PRIMARY    | 275513344 
tmp           | test       | deleted_at | 170639360 
tmp           | test       | is_active  |  97107968 

Lưu ý rằng mặc dù TIMESTAMP (4 Byte) dài gấp 4 lần TYNYINT (1 Byte), kích thước chỉ mục thậm chí không lớn gấp đôi. Nhưng kích thước chỉ mục có thể đáng kể nếu nó không vừa với bộ nhớ. Vì vậy, khi tôi thay đổi innodb_buffer_pool_size từ 1G đến 50M tôi nhận được những con số sau:

  • TINYINT:~ 960 mili giây
  • TIMESTAMP:~ 1500 mili giây

Cập nhật

Để giải quyết câu hỏi trực tiếp hơn, tôi đã thực hiện một số thay đổi đối với dữ liệu:

  • Thay vì TIMESTAMP, tôi sử dụng DATETIME
  • Vì các mục nhập thường hiếm khi bị xóa nên tôi sử dụng rand(1)<0.99 (1% đã bị xóa) thay vì rand(1)<0.5 (50% đã bị xóa)
  • Kích thước bảng đã thay đổi từ 10 triệu thành 1 triệu hàng.
  • SELECT COUNT(*) đã thay đổi thành SELECT *

Kích thước chỉ mục:

index_name | stat_value*@@innodb_page_size
------------------------------------------
PRIMARY    | 25739264
deleted_at | 12075008
is_active  | 11026432

Vì 99% deleted_at giá trị là NULL, không có sự khác biệt đáng kể về kích thước chỉ mục, mặc dù DATETIME không trống yêu cầu 8 Byte (MariaDB).

SELECT * FROM test WHERE is_active = 1;      -- 782 msec
SELECT * FROM test WHERE deleted_at is null; -- 829 msec

Bỏ cả hai chỉ mục cả hai truy vấn sẽ thực thi trong khoảng 350 mili giây. Và bỏ is_active cột deleted_at is null truy vấn thực thi trong 280 mili giây.

Lưu ý rằng đây vẫn không phải là một kịch bản thực tế. Bạn sẽ không muốn chọn 990 nghìn hàng trong số 1 triệu hàng và phân phối nó cho người dùng. Bạn cũng có thể sẽ có nhiều cột hơn (có thể bao gồm cả văn bản) trong bảng. Nhưng nó cho thấy rằng bạn có thể không cần is_active (nếu nó không thêm thông tin bổ sung) và bất kỳ chỉ mục nào trong trường hợp tốt nhất là vô dụng để chọn các mục nhập không bị xóa.

Tuy nhiên, một chỉ mục có thể hữu ích để chọn các hàng đã xóa:

SELECT * FROM test WHERE is_active = 0;

Thực thi trong 10 mili giây có chỉ mục và trong 170 mili giây không có chỉ mục.

SELECT * FROM test WHERE deleted_at is not null;

Thực thi trong 11 mili giây có chỉ mục và trong 167 mili giây không có chỉ mục.

Bỏ is_active cột nó thực thi trong 4 mili giây có chỉ mục và trong 150 mili giây không có chỉ mục.

Vì vậy, nếu tình huống này bằng cách nào đó phù hợp với dữ liệu của bạn, kết luận sẽ là:Bỏ is_active và không tạo chỉ mục trên deleted_at nếu bạn hiếm khi chọn các mục đã xóa. Hoặc điều chỉnh điểm chuẩn theo nhu cầu của bạn và đưa ra kết luận của riêng bạn.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Tạo một bảng mysql với một biến PHP

  2. Cách đồng bộ hóa cơ sở dữ liệu SQLServer và cơ sở dữ liệu MySQL

  3. Cấu trúc truy vấn để tạo bảng

  4. Hiển thị menu cây của cha mẹ đã chọn

  5. SQL trong mệnh đề với 0 đến nhiều tham số