MySQLの範囲検索でレコードが多すぎるとフルテーブルスキャンになってしまう現象

created_atが何月何日から何月何日のレコードをSELECTする場合に、ある量を超えるとEXPLAIN上ではフルテーブルスキャンの判定になってしまったのでどうしてなのか実験してみました。

実験は次のような環境で行いました。

OS: OS X El Capitan 10.11.3
CPU: 1.2 GHz Intel Core M
Memory: 8GB 1600 MHz DDR3

$ mysql --version
mysql  Ver 14.14 Distrib 5.6.28, for osx10.11 (x86_64) using  EditLine wrapper

準備

まず、range_testという名前のテーブルを作ります。

int型、bigint型、datetime型のカラムを作成して、それぞれ比較してみました。

カラム名 取りうる値の範囲
id bigint unsigned (PK) 1 〜 5,000,000
int_col int 0 〜 10,000
bigint_col bigint 1 〜 9,999,999
datetime_col datetime 2000-01-01 00:00:00 〜3000-01-08 00:00:00

インデックスが効くかどうかの実験なので、それぞれのカラムにインデックスを貼っておきます。

mysql> create database db_range_test;  
Query OK, 1 row affected (0.03 sec)

mysql> use db_range_test;
Database changed

mysql> create table range_test (
    -> id bigint unsigned not null auto_increment,
    -> int_col int,
    -> bigint_col bigint,
    -> datetime_col datetime,
    -> primary key (id),
    -> key idx_int (int_col),
    -> key idx_bigint (bigint_col),
    -> key idx_datetime (datetime_col)
    -> ) engine=InnoDB default charset utf8;
Query OK, 0 rows affected (0.11 sec)

こんな感じのスクリプトを書いて、MySQLに5,000,000件のダミーデータをINSERTします。

require 'sequel'
require 'mysql2'
require 'active_support'
require 'active_support/core_ext'

DB = Sequel.connect('mysql2://root@localhost/db_range_test')

(1..5_000_000).each do |i|
  int_r = rand(0..10_000)
  big_r = rand(0..10_000_000)
  dat_r = rand(0..1_000)
  DB[:range_test].insert(
    int_col: int_r,
    bigint_col: big_r,
    datetime_col: DateTime.new(2000, 1, 1).since(dat_r.years)
  )
end

5,000,000件入りました。 SELECT COUNT(*)に5秒弱かかるとは。。。

mysql> select count(*) from range_test;
+----------+
| count(*) |
+----------+
|  5000000 |
+----------+
1 row in set (4.96 sec)

mysql> select * from range_test limit 10;
+----+---------+------------+---------------------+
| id | int_col | bigint_col | datetime_col        |
+----+---------+------------+---------------------+
|  1 |    7521 |    8840230 | 2988-01-08 00:00:00 |
|  2 |    8951 |     617956 | 2454-01-03 12:00:00 |
|  3 |    4677 |    4115021 | 2111-01-01 18:00:00 |
|  4 |    8235 |    7919478 | 2906-01-07 12:00:00 |
|  5 |    5710 |    2487144 | 2958-01-07 12:00:00 |
|  6 |    9313 |       3383 | 2805-01-06 06:00:00 |
|  7 |    3602 |    9241458 | 2336-01-04 00:00:00 |
|  8 |    8950 |    8957220 | 2970-01-07 12:00:00 |
|  9 |    9052 |     731523 | 2865-01-06 06:00:00 |
| 10 |    5988 |    5204737 | 2121-01-01 06:00:00 |
+----+---------+------------+---------------------+
10 rows in set (0.00 sec)

実験

int

mysql> explain select * from range_test where 0 <= int_col and int_col <= 7;
+----+-------------+------------+-------+---------------+---------+---------+------+------+-----------------------+
| id | select_type | table      | type  | possible_keys | key     | key_len | ref  | rows | Extra                 |
+----+-------------+------------+-------+---------------+---------+---------+------+------+-----------------------+
|  1 | SIMPLE      | range_test | range | idx_int       | idx_int | 5       | NULL | 3849 | Using index condition |
+----+-------------+------------+-------+---------------+---------+---------+------+------+-----------------------+
1 row in set (0.01 sec)

mysql> select count(*) from range_test where 0 <= int_col and int_col <= 7;
+----------+
| count(*) |
+----------+
|     3850 |
+----------+
1 row in set (0.00 sec)


mysql> explain select * from range_test where 0 <= int_col and int_col <= 8;
+----+-------------+------------+-------+---------------+---------+---------+------+------+----------------------------------+
| id | select_type | table      | type  | possible_keys | key     | key_len | ref  | rows | Extra                            |
+----+-------------+------------+-------+---------------+---------+---------+------+------+----------------------------------+
|  1 | SIMPLE      | range_test | range | idx_int       | idx_int | 5       | NULL | 4355 | Using index condition; Using MRR |
+----+-------------+------------+-------+---------------+---------+---------+------+------+----------------------------------+
1 row in set (0.00 sec)

mysql> select count(*) from range_test where 0 <= int_col and int_col <= 8;
+----------+
| count(*) |
+----------+
|     4356 |
+----------+
1 row in set (0.01 sec)


mysql> explain select * from range_test where 0 <= int_col and int_col <= 1009;
+----+-------------+------------+-------+---------------+---------+---------+------+--------+----------------------------------+
| id | select_type | table      | type  | possible_keys | key     | key_len | ref  | rows   | Extra                            |
+----+-------------+------------+-------+---------------+---------+---------+------+--------+----------------------------------+
|  1 | SIMPLE      | range_test | range | idx_int       | idx_int | 5       | NULL | 929646 | Using index condition; Using MRR |
+----+-------------+------------+-------+---------------+---------+---------+------+--------+----------------------------------+
1 row in set (0.00 sec)

mysql> select count(*) from range_test where 0 <= int_col and int_col <= 1009;
+----------+
| count(*) |
+----------+
|   505016 |
+----------+
1 row in set (0.20 sec)


mysql> explain select * from range_test where 0 <= int_col and int_col <= 1010;
+----+-------------+------------+------+---------------+------+---------+------+---------+-------------+
| id | select_type | table      | type | possible_keys | key  | key_len | ref  | rows    | Extra       |
+----+-------------+------------+------+---------------+------+---------+------+---------+-------------+
|  1 | SIMPLE      | range_test | ALL  | idx_int       | NULL | NULL    | NULL | 4986946 | Using where |
+----+-------------+------------+------+---------------+------+---------+------+---------+-------------+
1 row in set (0.00 sec)

mysql> select count(*) from range_test where 0 <= int_col and int_col <= 1010;
+----------+
| count(*) |
+----------+
|   505547 |
+----------+
1 row in set (0.15 sec)

途中でExtraにUsing MRRというものが出るようになったのですが、どうやらMySQL 5.6から入ったMulti-Range Readというものがあるらしい。

MySQL :: MySQL 5.6 リファレンスマニュアル :: 8.2.1.13 Multi-Range Read の最適化

検索条件に合致するレコード数 全レコード数から占める割合 type Extra
〜 3,850 〜 0.0770% range Using index condition
4,356 〜 505,016 0.0871%〜10.1% range Using index condition; Using MRR
505,547 〜 10.1% 〜 ALL Using where

bitint

mysql> explain select * from range_test where 0 <= bigint_col and bigint_col <= 7843;
+----+-------------+------------+-------+---------------+------------+---------+------+------+-----------------------+
| id | select_type | table      | type  | possible_keys | key        | key_len | ref  | rows | Extra                 |
+----+-------------+------------+-------+---------------+------------+---------+------+------+-----------------------+
|  1 | SIMPLE      | range_test | range | idx_bigint    | idx_bigint | 9       | NULL | 3989 | Using index condition |
+----+-------------+------------+-------+---------------+------------+---------+------+------+-----------------------+
1 row in set (0.00 sec)

mysql> select count(*) from range_test where 0 <= bigint_col and bigint_col <= 7843;
+----------+
| count(*) |
+----------+
|     3990 |
+----------+
1 row in set (0.00 sec)


mysql> explain select * from range_test where 0 <= bigint_col and bigint_col <= 7844;
+----+-------------+------------+-------+---------------+------------+---------+------+------+----------------------------------+
| id | select_type | table      | type  | possible_keys | key        | key_len | ref  | rows | Extra                            |
+----+-------------+------------+-------+---------------+------------+---------+------+------+----------------------------------+
|  1 | SIMPLE      | range_test | range | idx_bigint    | idx_bigint | 9       | NULL | 3990 | Using index condition; Using MRR |
+----+-------------+------------+-------+---------------+------------+---------+------+------+----------------------------------+
1 row in set (0.00 sec)

mysql> select count(*) from range_test where 0 <= bigint_col and bigint_col <= 7844;
+----------+
| count(*) |
+----------+
|     3991 |
+----------+
1 row in set (0.00 sec)


mysql> explain select * from range_test where 0 <= bigint_col and bigint_col <= 898823;
+----+-------------+------------+-------+---------------+------------+---------+------+--------+----------------------------------+
| id | select_type | table      | type  | possible_keys | key        | key_len | ref  | rows   | Extra                            |
+----+-------------+------------+-------+---------------+------------+---------+------+--------+----------------------------------+
|  1 | SIMPLE      | range_test | range | idx_bigint    | idx_bigint | 9       | NULL | 982422 | Using index condition; Using MRR |
+----+-------------+------------+-------+---------------+------------+---------+------+--------+----------------------------------+
1 row in set (0.00 sec)

mysql> select count(*) from range_test where 0 <= bigint_col and bigint_col <= 898823;
+----------+
| count(*) |
+----------+
|   450211 |
+----------+
1 row in set (0.18 sec)

mysql> explain select * from range_test where 0 <= bigint_col and bigint_col <= 898824;
+----+-------------+------------+------+---------------+------+---------+------+---------+-------------+
| id | select_type | table      | type | possible_keys | key  | key_len | ref  | rows    | Extra       |
+----+-------------+------------+------+---------------+------+---------+------+---------+-------------+
|  1 | SIMPLE      | range_test | ALL  | idx_bigint    | NULL | NULL    | NULL | 4986946 | Using where |
+----+-------------+------------+------+---------------+------+---------+------+---------+-------------+
1 row in set (0.00 sec)

mysql> select count(*) from range_test where 0 <= bigint_col and bigint_col <= 898824;
+----------+
| count(*) |
+----------+
|   450212 |
+----------+
1 row in set (0.13 sec)
検索条件に合致するレコード数 全レコード数から占める割合 type Extra
〜 3,990 〜 0.0798% range Using index condition
3,991 〜 450,211 0.0798% 〜 9.00% range Using index condition; Using MRR
450,212 〜 9.00% 〜 ALL Using where

datetime

mysql> explain select * from range_test where '2000-01-01 00:00:00' <= datetime_col and datetime_col <= '2079-01-01 00:00:00';
+----+-------------+------------+-------+---------------+--------------+---------+------+--------+----------------------------------+
| id | select_type | table      | type  | possible_keys | key          | key_len | ref  | rows   | Extra                            |
+----+-------------+------------+-------+---------------+--------------+---------+------+--------+----------------------------------+
|  1 | SIMPLE      | range_test | range | idx_datetime  | idx_datetime | 6       | NULL | 905046 | Using index condition; Using MRR |
+----+-------------+------------+-------+---------------+--------------+---------+------+--------+----------------------------------+
1 row in set (0.01 sec)

mysql> select count(*) from range_test where '2000-01-01 00:00:00' <= datetime_col and datetime_col <= '2079-01-01 00:00:00';
+----------+
| count(*) |
+----------+
|   398998 |
+----------+
1 row in set (0.18 sec)


mysql> explain select * from range_test where '2000-01-01 00:00:00' <= datetime_col and datetime_col <= '2080-01-01 00:00:00';
+----+-------------+------------+------+---------------+------+---------+------+---------+-------------+
| id | select_type | table      | type | possible_keys | key  | key_len | ref  | rows    | Extra       |
+----+-------------+------------+------+---------------+------+---------+------+---------+-------------+
|  1 | SIMPLE      | range_test | ALL  | idx_datetime  | NULL | NULL    | NULL | 4986946 | Using where |
+----+-------------+------------+------+---------------+------+---------+------+---------+-------------+
1 row in set (0.00 sec)

mysql> select count(*) from range_test where '2000-01-01 00:00:00' <= datetime_col and datetime_col <= '2080-01-01 00:00:00';
+----------+
| count(*) |
+----------+
|   404030 |
+----------+
1 row in set (0.16 sec)
検索条件に合致するレコード数 全レコード数から占める割合 type Extra
〜 398,998 〜 7.98% range Using index condition; Using MRR
404,030 〜 8.08% 〜 ALL Using where

単純な実験ですが、全レコードの約9%より多いレコードを取得しようとすると、EXPLAIN上ではフルテーブルスキャンの戦略が選ばれてしまうようでした。

フルテーブルスキャンの戦略が選ばれたクエリを打ってみても、あまり実行時間に変化がない(0.02 sec前後)ので、本当にフルテーブルスキャンしているのかが気になりました。

途中まで実験してから思ったのですが、MySQLのパラメータをいじったら変化が出るのではないかとかも考えたのですが、追いきれなかったのでまた今度。。。


追記

http://spring-mt.hatenablog.com/entry/2016/02/18/010911

optimizer_traceなんてものがあるのですね…!

railsへの執着はもはや煩悩の域であり、開発者一同は瞑想したほうがいいと思います。 というチームでしたがISUCON5予選ダメでした #isucon

一昨年去年と出てて、今年が3回目のISUCONでした。 去年までは学生枠だったのですが、今年から社会人になってしまったので一般枠になってしまいました。

今年も、去年と同じ id:cnosuke さんと id:k0kubun さんと出ました。

競技中についてはk0kubunさんが大体全部書いてくれました → http://k0kubun.hatenablog.com/entry/2015/09/27/225243

上の記事のとおりですが、k0kubunさんががアプリケーション周りを全体的に、cnosukeさんがnginxとかredis周りとか、自分がMySQL周りを、なんとなく3人で分担してました。

したこと

ひたすらボトルネックを探してそこを潰す、潰したらまた探して潰す、、、という感じの流れでした。 k0kubunさんの記事に書いてあるようにジワジワとスコアが上がっていくのは見ていて楽しかったです。

New Relicとrack-lineprofがひたすら便利でした。 あと、cnosukeさんが書いたnginxのログからアクセス頻度見るツールとか使ってました。

自分はMySQL周りを見ていたので、slow queryを吐き出させてそこから頻出クエリと時間がかかっているクエリを探して、インデックス貼ったりクエリ改善できるかを模索したりしてました。 slow queryを吐き出す設定が何故かファイルに書いても動かなかったので、こんな感じで直接打ってました(適当)。

mysql> SET GLOBAL slow_query_log = 1; # オフにするときは0にする
mysql> SET GLOBAL slow_query_log_file = /var/log/mysql/slow.log;
mysql> SET GLOBAL long_query_time = 0;

以前は適当に手当たり次第「これ直りそうじゃない?」みたいなものを見つけて改善しようとしてましたが、 それだと当たり前ですが効果が全然出ないことが多いので、「推測するな、計測せよ」がメチャメチャ大切だと思いました。


結局最終的にスコア11045で終わりましたが、終了直前にベンチ回したのでもしかしたら若干違うかもです。

足切りラインが14000くらいだったので、もうちょっとで本戦にいけるかもしれなかったので悔しいです(ヽ´ω`)

今年は残念でしたが、また来年開催されましたらぜひ参加したいです!!!

JavaのライブラリのテストをJRuby+minitestで書く

お前は何と戦っているんだ感が半端ないですが、タイトルの通りJavaで書いたライブラリのテストをJRuby+minitestで書いてみました。

テストを書く対象のライブラリは、よくある(?)行列演算を行うやつです。 例としてMyMatrixLib.jar (net.rkmathi.lib.MyMatrixLib)という名前にしてみます。

JRuby, minitestのインストール

rbenvを使っているので、それ経由で入れました。

$ rbenv install -l | grep jruby
...
jruby-1.7.16
jruby-1.7.16.1
jruby-9.0.0.0-dev
jruby-9000-dev
...

jruby-1.7.16.1にしました。

$ rbenv install jruby-1.7.16.1

テスト書くディレクトリに移動して、rbenv localjrubyを使うようにします。

$ cd /path/to/test_directory
$ rbenv local jruby-1.7.16.1
$ rbenv rehash
$ jruby --version
jruby 1.7.16.1 (1.9.3p392) 2014-10-28 4e93f31 on Java HotSpot(TM) 64-Bit Server VM 1.8.0_25-b17 +jit [darwin-x86_64]

minitestのインストールをします。

$ jruby -S gem install minitest

ライブラリのJARを持ってくる

$ cd /path/to/test_directory
$ cp /path/to/MyMatrixLib.jar .

JRuby+minitestでテストを書く

とりあえず、get()とplus()とminus()のテストを書いてみるとこうなります。

require 'minitest'
require 'minitest/autorun'

require 'java'
require_relative './MyMatrixLib.jar'

import 'net.rkmathi.lib.MyMatrixLib'

class TestMyMatrixLib < Minitest::Test
  def setup
    @d1 = rand(1000.0)
    @d2 = rand(1000.0)
    @m1 = MyMatrixLib.new(3, 2, @d1)  # 3x2ですべての要素が@d1の行列を生成
    @m2 = MyMatrixLib.new(3, 2, @d2)  # 3x2ですべての要素が@d2の行列を生成
  end

  # get(r, c) => double: 行列のr行c列目の要素を取得
  def test_get
    each_assert_get @m1, @d1
    each_assert_get @m2, @d2
  end

  # plus(matrix) => MyMatrix: 行列のそれぞれの要素を足した行列を生成
  def test_plus
    d_res = @d1 + @d2
    m_res = @m1.plus(@m2)  # @m1と@m2のそれぞれの要素を足した結果の行列
    each_assert_get m_res, d_res
  end

  # minus(matrix) => MyMatrix: 行列のそれぞれの要素を引いた行列を生成
  def test_minus
    d_res = @d1 - @d2
    m_res = @m1.minus(@m2)  # @m1と@m2のそれぞれの要素を引いた結果の行列
    each_assert_get m_res, d_res
  end

  private

  # 行列の各要素をそれぞれgetするのが面倒なのでメソッド化
  def each_assert_get(m, d)
    for r in 0...m.get_row_dimension do
      for c in 0...m.get_column_dimension do
        assert_equal m.get(r, c), d
      end
    end
  end

  ...

end

と、こんな感じで書くことができます。

ちなみにJUnitだと...

public class MyMatrixLibTest {
    @Before
    public void setUp() throws Exception {
        MyMatrixLib d1 = Math.random() * 1000.0;
        MyMatrixLib d2 = Math.random() * 1000.0;
        MyMatrixLib m1 = new MyMatrixLib(3, 2, d1);
        MyMatrixLib m2 = new MyMatrixLib(3, 2, d2);
    }

    @Test
    public void testGet() {
        eachAssertGet(m1, d1);
        eachAssertGet(m2, d2);
    }

    @Test
    public void testPlus() {
        double d_res = d1 + d2;
        MyMatrixLib m_res = m1.plus(m2);
        eachAssertGet(m_res, d_res);
    }

    @Test
    public void testMinus() {
        double d_res = d1 - d2;
        MyMatrixLib m_res = m1.minus(m2);
        eachAssertGet(m_res, d_res);
    }

    private void eachAssertGet(MyLibMatrix m, double d) {
        for (int row = 0; row < m.getRowDimension(); row++) {
            for (int column = 0; column < m.getRowDimension(); column ++) {
                assertEquals(m.get(row, column), d);
            }
        }
    }
}

簡単な演算のテスト部分しか比較しませんでしたが、書いてて楽には思えました。

ですが、JRubyを書いていると文法とか変数の型をミスった時に吐かれる例外がよくわからないことになることもあるので、わざわざJRubyでテスト書くのは微妙かも...

VPS上にSoftEther VPN ServerをセットアップしてOS Xからつなぐ

HDD容量を少なくすればめちゃ安いVPS( http://www.idcf.jp/cloud/ )を教えてもらったので、ここにSoftEtherVPN Serverをセットアップしてみました。

ちなみに、仮想マシンを作成するときに「テンプレート」からだとHDD容量が最低15GBなので540円/月ですが、「ISO」から作るようにすると最低1GBから選べるようになります。例えば5GBにすれば324円/月で済みます。

ポートの設定

VPSのコントロールパネル側でファイアウォールの設定があるので、

のポートを開けておきます。

SoftEther VPNのダウンロード

SoftEther ダウンロードセンターから、SoftEther VPN (Freeware)SoftEther VPN ServerLinuxIntel x64 / AMD64 (64bit)を選んで、最新ビルドのリンクのアドレスをメモっておきます。

あとで、OSをインストールしたらこのリンクから引っ張ってきます。

OSのインストールとファイルの配置

適当に、Ubuntu Server 14.04 amd64をインストールしておきました。

### 必要なパッケージのインストール
~$ sudo aptitude update
~$ sudo aptitude upgrade
~$ sudo aptitude install build-essential sysv-rc-conf

### さっきのリンクからダウンロード
~$ wget http://jp.softether-download.com/files/XXX/softether-vpnserver-XXX-linux-x64-64bit.tar.gz
~$ tar xvf softether-vpnserver-XXX-linux-x64-64bit.tar.gz
~$ cd vpnserver

### 確認したら、1でAcceptしてmake
~/vpnserver$ make
1
1
1

### vpnserverのパーミッションを変更
~/vpnserver$ chmod 600 *
~/vpnserver$ chmod 700 vpncmd vpnserver
~/vpnserver$ cd ../
~$ sudo mv vpnserver /usr/local/
~$ sudo chown -R root:root /usr/local/vpnserver
~$ cd /usr/local/vpnserver

### 動作確認
/usr/local/vpnserver$ sudo ./vpncmd
3
check
exit

/usr/local/vpnserver$ cd

### initスクリプトを書いて、パーミッションを755にしておく
~$ sudo chmod 755 /etc/init.d/vpnserver
~$ sudo cat /etc/init.d/vpnserver
#!/bin/sh
# description: SoftEther VPN Server
DAEMON=/usr/local/vpnserver/vpnserver
LOCK=/var/lock/vpnserver
test -x $DAEMON || exit 0
case "$1" in
start)
$DAEMON start
touch $LOCK
;;
stop)
$DAEMON stop
rm $LOCK
;;
restart)
$DAEMON stop
sleep 3
$DAEMON start
;;
*)
echo "Usage: $0 {start|stop|restart}"
exit 1
esac
exit 0

### sysv-rc-confでvpnserverの2,3,4,5にチェック
~$ sudo sysv-rc-conf
...

### 再起動
~$ sudo reboot

SoftEther VPN Serverのセットアップ

~$ cd /usr/local/vpnserver

/usr/local/vpnserver$ sudo ./vpncmd
1
localhost
(Enter)

### VPN Serverのパスワードを設定
VPN Server> ServerPasswordSet
(パスワードを設定)

### 仮想ハブを作成 ここではVPNHUBという名前にしてある
VPN Server> HubCreate
Name of Virtual Hub to be created: VPNHUB

### VPNHUBに切り替え
VPN Server> Hub VPNHUB

### SecureNatを有効に
VPN Server/VPNHUB> SecureNatEnable

### ユーザを作成 ここではvpnという名前にしてある
VPN Server/VPNHUB> UserCreate
vpn
(Enter)
(Enter)
(Enter)

### 上で作ったvpnユーザのパスワードを設定
VPN Server/VPNHUB> UserPasswordSet
vpn
(VPN User Password)
(VPN User Password)

### IPSecを有効に
VPN Server/VPNHUB> IPSecEnable
Enable L2TP over IPsec Server Function (yes / no): yes
Enable Raw L2TP Server Function (yes / no): no
Enable EtherIP / L2TPv3 over IPsec Server Function (yes / no): no
Pre Shared Key for IPsec (Recommended: 9 letters at maximum): (IPsec Secret Key)
Default Virtual HUB in a case of omitting the HUB on the Username: VPNHUB

VPN Server/VPNHUB> exit

$ sudo service vpnserver restart

OS X(クライアント)側の設定

システム環境設定ネットワーク→左下の+マークで追加

f:id:rkmathii:20141128000937p:plain

↑画像のサーバアドレスアカウント名を埋めたら、下にある認証設定…をクリック

f:id:rkmathii:20141128001148p:plain

ユーザ認証 パスワードに(VPN User Password)を、コンピュータ認証 共有シークレットに(IPsec Key)を入力

これで接続ができるように(┐「ε:)

GitLabでMaven Repositoryを作ってGradleから使う

研究室でJavaのプログラムを書いているのですが、ライブラリを研究室内で共有するときにMaven Repositoryを立てたらいいのではないかと思ったので、GitLab上で使うようにしました。

想定するプログラム

  • ライブラリ(MyLib)
  • MyLibを使用するプログラム(MyProgram)

MyLibのbuild.gradle

apply plugin: 'idea'
apply plugin: 'java'
apply plugin: 'maven'

def defaultEncoding = 'UTF-8'
[compileJava, compileTestJava]*.options*.encoding = defaultEncoding
sourceCompatibility = 1.7
targetCompatibility = 1.7

group = 'net.rkmathi'
archivesBaseName = 'mylib'
version = '1.0.0'

repositories {
    maven { url System.getenv('HOME') + '/.m2/repository' }
    mavenCentral()
}

dependencies {
    testCompile 'junit:junit:4.11'
}

uploadArchives.repositories.mavenDeployer {
    repository(url: "file:${projectDir}/maven")
}

これでgradle uploadArchivesを実行すると、mavenディレクトリ以下に出力されます。

  • uploadArchivesで出力したら、gitリポジトリにそのディレクトリも追加して、GitLabへプッシュします。

MyProgramのbuild.gradle

apply plugin: 'idea'
apply plugin: 'java'
apply plugin: 'maven'

def defaultEncoding = 'UTF-8'
[compileJava, compileTestJava]*.options*.encoding = defaultEncoding
sourceCompatibility = 1.7
targetCompatibility = 1.7

group = 'net.rkmathi'
archivesBaseName = 'myprogram'
version = '1.0.0'

repositories {
    maven { url System.getenv('HOME') + '/.m2/repository' }
    maven { url 'http://<<GitLab Address>>/<<User Name>>/mylib/raw/master/maven' }
    mavenCentral()
}

dependencies {
    compile 'net.rkmathi:mylib:1.0.0'
    testCompile 'junit:junit:4.11'
}

uploadArchives.repositories.mavenDeployer {
    repository(url: "file:${projectDir}/maven")
}

これで、MyProgramからMyLibを使うことができました。

  • http://<<GitLabのアドレス>>/<<ユーザ名>>/<<プロジェクト名>>/raw/mastermaven repositoriesの場所に指定することによって、GitLab上にあるライブラリを取得できるようになります。

ワーイ